No difference (from git reset
man page) in term of default parameter:
The <tree-ish>/<commit>
defaults to HEAD
in all forms.
That message initially did not include HEAD: commit 3c1eb9c, Jan. 2007, git 1.5.0-rc1, but since the default is not always known, the help message makes it clear to which commit you are supposed to reset.
HEAD
appears in commit 367c988, Nov. 2007, Git 1.5.4:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
torek points out an actual difference in the comments:
By specifying HEAD
, you guarantee that the first word after HEAD
is taken as a path name.
For instance, suppose you run git reset zorg
. Is zorg
a tree-ish, such as a tag name, or is it a path name, ./zorg
?
Git's answer is: it's a tree-ish if git rev-parse
can turn it into a tree ID, otherwise it's a path.
You can either write git reset -- zorg
or git reset HEAD zorg
to make sure that git treats it as a path.
See more on the double hyphen syntax ( --
) in "Deleting a badly named git branch".
The OP skube adds in the comments:
As an aside, they do suggest it for discarding changes in working directory
(i.e git checkout -- <file>
).
It just seems inconsistent with git reset HEAD <file>
.
While git reset
man page clearly indicates the lack of tree-ish in git reset <tree-ish> -- <paths>
means HEAD, it is not so for git checkout <tree-ish> -- <paths>
.
git checkout <tree-ish> -- <pathspec>
When <paths>
are given, git checkout
does not switch branches.
It updates the named paths in the working tree from the index file or from a named <tree-ish>
(most often a commit).
That means git checkout -- path
will override the working tree with what has already been staged (git add
'ed).
While git reset -- PATH
(being the mixed form of git reset) will reset the index with what HEAD contains (effectively un-staging what was added)
git reset
and git checkout
don't use the same default, and:
- you can represent the default tree for
git reset <tree-ish> <file>
: HEAD
.
Hence git reset HEAD <file>
;
- but you cannot represent the default parameter when you don't provide a tree for
git checkout
: it is the index.
Hence git checkout -- file
.
The --
has to be used in the git checkout
case, since there is only one parameter, and it needs to be clear that parameter represents files.
Note that git checkout HEAD files
is different: torek mentions in the comments
git checkout HEAD path
copies from the HEAD
commit (the tree-ish) to the index and then on to the working dir.
Note: with Git 2.23+, August 2019, you might use git restore
instead
See the examples:
To restore a file in the index to match the version in HEAD (this is the same as using git-reset
)
$ git restore --staged hello.c
man page:
git restore --staged hello.c
does not specify a source, and restore the index only (--staged
): it does so (by default) using HEAD as source.
By default, the restore sources for working tree and the index are the index and HEAD respectively.
--source
could be used to specify a commit as the restore source.
Other examples:
You can restore both the index and the working tree (this the same as using git-checkout
)
$ git restore --source=HEAD --staged --worktree hello.c
or the short form which is more practical but less readable:
$ git restore -s@ -SW hello.c
git restore
is a more natural command name, and has no ambiguity.
git restore --staged -- afile
, with Git 2.23 (August 2019). See my edited answer below – Titanesque