git reset 与 git reset HEAD
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33849704/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
git reset vs git reset HEAD
提问by skube
Every time a file has been staged, Git offers helpful instructions in the event you needed to unstage a file:
每次暂存文件时,Git 都会在您需要取消暂存文件时提供有用的说明:
(use "git reset HEAD <file>..." to unstage)
(use "git reset HEAD <file>..." to unstage)
However the decent Git Tutorials by Atlassiansimply say:
然而,Atlassian的体面Git 教程只是简单地说:
git reset <file>
git reset <file>
This seems more straightforward, so why the difference?
这看起来更简单,那么为什么不同呢?
回答by VonC
No difference (from git reset
man page) in term of default parameter:
在默认参数方面没有区别(来自git reset
手册页):
The
<tree-ish>/<commit>
defaults toHEAD
in all forms.
该
<tree-ish>/<commit>
默认为HEAD
所有形式。
That message initially did notinclude HEAD: commit 3c1eb9c, Jan. 2007, git 1.5.0-rc1, but since the default is notalways known, the help message makes it clear to which commit you are supposed to reset.
该消息最初不包括 HEAD: commit 3c1eb9c, Jan. 2007, git 1.5.0-rc1,但由于默认值并不总是已知的,帮助消息明确指出您应该重置哪个提交。
HEAD
appears in commit 367c988, Nov. 2007, Git 1.5.4:
HEAD
出现在提交 367c988,2007 年 11 月,Git 1.5.4 中:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
torekpoints out an actual difference in the comments:
By specifying
HEAD
, you guarantee that the first word afterHEAD
is taken as a path name.
For instance, suppose you rungit reset zorg
. Iszorg
a tree-ish, such as a tag name, or is it a path name,./zorg
?
Git's answer is: it's a tree-ish ifgit rev-parse
can turn it into a tree ID, otherwise it's a path.
You can either writegit reset -- zorg
orgit reset HEAD zorg
to make sure that git treats it as a path.
通过指定
HEAD
,您可以保证后面的第一个单词HEAD
被用作路径名。
例如,假设您运行git reset zorg
. 是zorg
树状的,例如标签名,还是路径名,./zorg
?
Git 的回答是:如果git rev-parse
能把它变成树 ID,它就是一个树状的,否则它就是一个路径。
您可以编写git reset -- zorg
或git reset HEAD zorg
确保 git 将其视为路径。
See more on the double hyphen syntax ( --
) in "Deleting a badly named git branch".
请参阅--
“删除名称错误的 git 分支”中有关双连字符语法 ( ) 的更多信息。
The OP skubeadds in the comments:
As an aside, they do suggest it for discarding changes in working directory
(i.egit checkout -- <file>
).
It just seems inconsistent withgit reset HEAD <file>
.
顺便说一句,他们确实建议放弃工作目录中的更改
(即git checkout -- <file>
)。
它似乎与git reset HEAD <file>
.
While git reset
man pageclearly 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 reset
手册页清楚地表明git reset <tree-ish> -- <paths>
HEAD 中缺少树形结构,但对于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 fileor from a named<tree-ish>
(most often a commit).
当
<paths>
给出时,git checkout
不切换分支。
它从索引文件或命名<tree-ish>
(通常是提交)更新工作树中的命名路径。
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 indexwith what HEAD contains (effectively un-staging what was added)
这意味着git checkout -- path
将使用已经上演的内容(git add
'ed)覆盖工作树。
虽然git reset -- PATH
(作为 git reset 的混合形式)将使用 HEAD 包含的内容重置索引(有效地取消添加添加的内容)
git reset
and git checkout
don't use the same default, and:
git reset
并且git checkout
不要使用相同的默认值,并且:
- you can represent the default tree for
git reset <tree-ish> <file>
:HEAD
.
Hencegit reset HEAD <file>
; - but you cannot represent the default parameter when you don't provide a tree for
git checkout
: it is the index.
Hencegit checkout -- file
.
- 您可以代表以下的默认树
git reset <tree-ish> <file>
:HEAD
。
因此git reset HEAD <file>
; - 但是当您不为 提供树时,您不能表示默认参数
git checkout
:它是索引。
因此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.
在--
已在使用git checkout
的情况下,由于只有一个参数,它需要明确的是,参数表示的文件。
Note that git checkout HEAD files
is different: torekmentions in the comments
请注意,这git checkout HEAD files
是不同的:torek在评论中提到
git checkout HEAD path
copies from theHEAD
commit (the tree-ish) to the index and then on to the working dir.
git checkout HEAD path
从HEAD
提交(树形)复制到索引,然后复制到工作目录。
Note: with Git 2.23+, August 2019, you might use git restore
instead
注意:对于 Git 2.23+,2019 年 8 月,您可以git restore
改用
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
恢复索引中的文件以匹配 HEAD 中的版本(这与使用相同
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.
git restore --staged hello.c
不指定源,仅恢复索引 ( --staged
):它这样做(默认情况下)使用 HEAD 作为源。
By default, the restore sourcesfor working tree and the index are the index and HEAD respectively.
--source
could be used to specify a commit as the restore source.
默认情况下,工作树和索引的恢复源分别是索引和 HEAD。
--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-checkout
)$ git restore --source=HEAD --staged --worktree hello.c
或者更实用但可读性较差的简短形式:
$ git restore -s@ -SW hello.c
git restore
is a more natural command name, and has no ambiguity.
git restore
是一个更自然的命令名称,没有歧义。
回答by code_dredd
By default, git reset
is equivalent to git reset HEAD
默认情况下,git reset
相当于git reset HEAD
Quoting the man page (my emphasis):
引用手册页(我的重点):
git-reset - Reset current HEAD to the specified state.
git reset [-q] [<tree-ish>] [--] <paths>… git reset (--patch | -p) [<tree-ish>] [--] [<paths>…?] git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
In the first and second form, copy entries from <tree-ish> to the index. In the third form, set the current branch head (HEAD) to <commit>, optionally modifying index and working tree to match. The <tree-ish>/<commit> defaults to HEAD in all forms.
[...]
git reset [-q] [<tree-ish>] [--] <paths>…?
This form resets the index entries for all <paths> to their state at <tree-ish>. (It does not affect the working tree or the current branch.)
This means that
git reset <paths>
is the opposite ofgit add <paths>
.
git-reset - 将当前 HEAD 重置为指定状态。
git reset [-q] [<tree-ish>] [--] <paths>… git reset (--patch | -p) [<tree-ish>] [--] [<paths>…?] git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
在第一种和第二种形式中,将条目从 <tree-ish> 复制到索引。在第三种形式中,将当前分支头(HEAD)设置为<commit>,可选择修改索引和工作树以匹配。<tree-ish>/<commit> 在所有形式中默认为 HEAD。
[...]
git reset [-q] [<tree-ish>] [--] <paths>…?
此表单将所有 <paths> 的索引条目重置为它们在 <tree-ish> 处的状态。(它不会影响工作树或当前分支。)
这意味着
git reset <paths>
与 相反git add <paths>
。
From this you see that there's no actual difference in behavior.
从这里你可以看到行为上没有实际差异。
This seems more straightforward, so why the difference?
这看起来更简单,那么为什么不同呢?
Since they're both the same, you might as well use the shortest version of the two.
由于它们都是相同的,您不妨使用两者中最短的版本。
回答by Grzegorz Kowalski
First time, before any commit the HEAD does not exist, then we get:
第一次,在任何提交之前 HEAD 不存在,然后我们得到:
$git reset HEAD stagedFile
fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree