141

http://norbauer.com/notebooks/code/notes/git-revert-reset-a-single-file

I have found a post.

But still don't know what is the difference between

  1. git checkout <filename>

  2. git checkout -- <filename>

In what situation I should use first one and second one respectively?

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
TheOneTeam
  • 25,806
  • 45
  • 116
  • 158
  • 1
    See also [Meaning of Git checkout double dashes](http://stackoverflow.com/q/13321458/456814). –  May 23 '14 at 20:37

4 Answers4

267

The special "option" -- means "treat every argument after this point as a file name, no matter what it looks like." This is not Git-specific, it's a general Unix command line convention. Normally you use it to clarify that an argument is a file name rather than an option, e.g.

rm -f      # does nothing
rm -- -f   # deletes a file named "-f"

git checkout1 also takes -- to mean that subsequent arguments are not its optional "treeish" parameter specifying which commit you want.

So in this context it's safe to use -- always, but you need it when the file you want to revert has a name that begins with -, or is the same as the name of a branch. Some examples for branch/file disambiguation:

git checkout README     # would normally discard uncommitted changes
                        # to the _file_ "README"

git checkout master     # would normally switch the working copy to
                        # the _branch_ "master"

git checkout -- master  # discard uncommitted changes to the _file_ "master"

and option/file disambiguation:

git checkout -p -- README  # interactively discard uncommitted changes
                           # to the file "README"

git checkout -- -p README  # unconditionally discard all uncommitted
                           # changes to the files "-p" and "README"

I'm not sure what you do if you have a branch whose name begins with -. Perhaps don't do that in the first place.


1 in this mode; "checkout" can do several other things as well. I have never understood why git chose to implement "discard uncommitted changes" as a mode of the "checkout" subcommand, rather than "revert" like most other VCSes, or "reset" which I think might make more sense in git's own terms.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • 14
    git checkout checks out the branch . git checkout -- checks out the index version of the file . – dunni Jul 03 '11 at 09:33
  • 3
    Thanks, unfortunately the git documentation doesn't really explain this – Carlton Dec 13 '13 at 10:57
  • 1
    Regarding "Unix convention": indeed `--` as a separator between options and arguments is widely implemented. It works for any program/utility that uses POSIX `getopt(3)` to handle its command line options, (see `man 3 getopt`), shell-scripts which use `getopt(1)`, and some programs which implement it themselves, but is not _universally guaranteed_ to work. – arielf Mar 22 '16 at 17:56
  • 1
    Hah! I simply read an example way back when of how to discard working changes, having forgotten seeing this convention in other command-line programs, assumed that `--` meant 'negate changes' _a la_ C/C++ - and have been thinking that ever since. Mind blown! – underscore_d Jul 19 '16 at 13:38
  • For people like me: don't get confused by name master, he means file named master and not the branch. – HarsH Aug 14 '19 at 23:54
  • @HarsH What part of the answer did you find confusing? I would like to clarify it. – zwol Aug 15 '19 at 16:13
11

Anything following the -- is treated as a filename (not as a program argument). This is important if, for example, you have filenames which start with dashes.

jtbandes
  • 115,675
  • 35
  • 233
  • 266
0
git checkout -- filename

will replace the version of the file you have in working directory with the one you have in index(staging area).

git checkout filename

will try to checkout the branch with the same name, if it doesn't exist then it will perform same operation as git checkout -- <filename>

SwissCodeMen
  • 4,222
  • 8
  • 24
  • 34
0

The difference between git checkout <filename> and git checkout -- <filename> lies in the handling of unmerged changes.

git checkout <filename> discards the changes in the current branch and replaces the file with the version from the specified branch or commit. If you have unmerged changes in the file, this command will fail and you'll get an error message.

git checkout -- <filename> discards all changes in the file, including any unmerged changes. This is useful when you want to completely discard your local changes and start over with the version from the specified branch or commit.

In summary, git checkout <filename> is used to switch to a specific version of a file while preserving the changes that have been merged into the current branch, while git checkout -- <filename> discards all changes in a file, including unmerged changes.