Meaning of Git checkout double dashes

ID : 10346

viewed : 24

Tags : gitgit-checkoutgit

Top 5 Answer for Meaning of Git checkout double dashes

vote vote

94

Suppose I have a file named path/to/file.txt in my Git repository, and I want to revert changes on it.

git checkout path/to/file.txt 

Now suppose that the file is named master...

git checkout master 

Whoops! That changed branches instead. The -- separates the tree you want to check out from the files you want to check out.

git checkout -- master 

It also helps us if some freako added a file named -f to our repository:

git checkout -f      # wrong git checkout -- -f   # right 

This is documented in git-checkout: Argument Disambiguation.

vote vote

82

The double dash "--" means "end of command line flags" i.e. it tells the preceding command not to try to parse what comes after command line options.

vote vote

78

Note that you would not need, since Git 2.5 (Q2 2015) a '--' if your argument includes wildcard (*)

An heuristic to help the "git <cmd> <revs> <pathspec>" command line convention to catch mistyped paths is to make sure all the non-rev parameters in the later part of the command line are names of the files in the working tree, but that means "git grep $str -- \*.c" must always be disambiguated with "--", because nobody sane will create a file whose name literally is asterisk-dot-see.

Git 2.5 looses the heuristic to declare that with a wildcard string the user likely meant to give us a pathspec.

git checkout 'a*' # same as git checkout -- 'a*' 

See commit 28fcc0b (02 May 2015) by Duy Nguyen (nguyenlocduy).
(Merged by Junio C Hamano -- gitster -- in commit 949d167, 19 May 2015)

pathspec: avoid the need of "--" when wildcard is used

When "--" is lacking from the command line and a command can take both revs and paths, the idea is if an argument can be seen as both an extended SHA-1 and a path, then "--" is required or git refuses to continue.
It's currently implemented as:

  • (1) if an argument is rev, then it must not exist in worktree
  • (2) else, it must exist in worktree
  • (3) else, "--" is required.

These rules work for literal paths, but when non-literal pathspec is involved, it almost always requires the user to add "--" because it fails (2) and (1) is really rarely met (take "*.c" for example, (1) is met if there is a ref named "*.c").

This patch modifies the rules a bit by considering any valid (*) wildcard pathspec "exist in worktree".
The rules become:

  • (1) if an arg is a rev, then it must either exist in worktree or not be a valid wildcard pathspec.
  • (2) else, it either exists in worktree or is a wildcard pathspec
  • (3) else, "--" is required.

With the new rules, "--" is not needed most of the time when wildcard pathspec is involved.


With Git 2.26 (Q1 2020), the disambiguation logic to tell revisions and pathspec apart has been tweaked so that backslash-escaped glob special characters do not count in the "wildcards are pathspec" rule.

See commit 39e21c6 (25 Jan 2020) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit 341f8a6, 12 Feb 2020)

verify_filename(): handle backslashes in "wildcards are pathspecs" rule

Reported-by: David Burström
Signed-off-by: Jeff King

Commit 28fcc0b71a (pathspec: avoid the need of "--" when wildcard is used, 2015-05-02) allowed:

git rev-parse '*.c' 

without the double-dash.

But the rule it uses to check for wildcards actually looks for any glob special.
This is overly liberal, as it means that a pattern that doesn't actually do any wildcard matching, like "a\b", will be considered a pathspec.

If you do have such a file on disk, that's presumably what you wanted.
But if you don't, the results are confusing: rather than say "there's no such path a\b", we'll quietly accept it as a pathspec which very likely matches nothing (or at least not what you intended).
Likewise, looking for path "a\*b" doesn't expand the search at all; it would only find a single entry, "a*b".

This commit switches the rule to trigger only when glob metacharacters would expand the search, meaning both of those cases will now report an error (you can still disambiguate using "--", of course; we're just tightening the DWIM heuristic).

(DWIM: Do What I Mean)

Note that we didn't test the original feature in 28fcc0b71a at all.
So this patch not only tests for these corner cases, but also adds a regression test for the existing behavior.

vote vote

62

vote vote

60

For those who don't want to create a custom dialog but still prefer a 100% WPF way and don't want to use separate DDLs, additional dependencies or outdated APIs, I came up with a very simple hack using the Save As dialog.

No using directive needed, you may simply copy-paste the code below !

It should still be very user-friendly and most people will never notice.

The idea comes from the fact that we can change the title of that dialog, hide files, and work around the resulting filename quite easily.

It is a big hack for sure, but maybe it will do the job just fine for your usage...

In this example I have a textbox object to contain the resulting path, but you may remove the related lines and use a return value if you wish...

// Create a "Save As" dialog for selecting a directory (HACK) var dialog = new Microsoft.Win32.SaveFileDialog(); dialog.InitialDirectory = textbox.Text; // Use current value for initial dir dialog.Title = "Select a Directory"; // instead of default "Save As" dialog.Filter = "Directory|*.this.directory"; // Prevents displaying files dialog.FileName = "select"; // Filename will then be "select.this.directory" if (dialog.ShowDialog() == true) {     string path = dialog.FileName;     // Remove fake filename from resulting path     path = path.Replace("\\select.this.directory", "");     path = path.Replace(".this.directory", "");     // If user has changed the filename, create the new directory     if (!System.IO.Directory.Exists(path)) {         System.IO.Directory.CreateDirectory(path);     }     // Our final value is in path     textbox.Text = path; } 

The only issues with this hack are :

  • Acknowledge button still says "Save" instead of something like "Select directory", but in a case like mines I "Save" the directory selection so it still works...
  • Input field still says "File name" instead of "Directory name", but we can say that a directory is a type of file...
  • There is still a "Save as type" dropdown, but its value says "Directory (*.this.directory)", and the user cannot change it for something else, works for me...

Most people won't notice these, although I would definitely prefer using an official WPF way if microsoft would get their heads out of their asses, but until they do, that's my temporary fix.

Top 3 video Explaining Meaning of Git checkout double dashes

Related QUESTION?