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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 11:32:33  来源:igfitidea点击:

git reset vs git reset HEAD

gitgit-resetunstage

提问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 resetman page) in term of default parameter:

在默认参数方面没有区别(来自git reset手册页):

The <tree-ish>/<commit>defaults to HEADin 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,但由于默认值并不总是已知的,帮助消息明确指出您应该重置哪个提交。

HEADappears 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:

torek指出了评论中的实际差异:

By specifying HEAD, you guarantee that the first word after HEADis taken as a path name.
For instance, suppose you run git reset zorg. Is zorga 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-parsecan turn it into a tree ID, otherwise it's a path.
You can either write git reset -- zorgor git reset HEAD zorgto make sure that git treats it as a path.

通过指定HEAD,您可以保证后面的第一个单词HEAD被用作路径名。
例如,假设您运行git reset zorg. 是zorg树状的,例如标签名,还是路径名,./zorg
Git 的回答是:如果git rev-parse能把它变成树 ID,它就是一个树状的,否则它就是一个路径。
您可以编写git reset -- zorggit 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:

OP skube增加的评论

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>.

顺便说一句,他们确实建议放弃工作目录中的更改
(即git checkout -- <file>)。
它似乎与git reset HEAD <file>.

While git resetman 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 checkoutdoes 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 -- pathwill 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 resetand git checkoutdon't use the same default, and:

git reset并且git checkout不要使用相同的默认值,并且:

  • 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.
  • 您可以代表以下的默认树git reset <tree-ish> <file>HEAD
    因此git reset HEAD <file>
  • 但是当您不为 提供树时,您不能表示默认参数git checkout:它是索引。
    因此git checkout -- file

The --has to be used in the git checkoutcase, since there is only one parameter, and it needs to be clear that parameter represents files.

--已在使用git checkout的情况下,由于只有一个参数,它需要明确的是,参数表示的文件

Note that git checkout HEAD filesis different: torekmentions in the comments

请注意,这git checkout HEAD files是不同的:torek在评论中提到

git checkout HEAD pathcopies from the HEADcommit (the tree-ish) to the index and then on to the working dir.

git checkout HEAD pathHEAD提交(树形)复制到索引,然后复制到工作目录。



Note: with Git 2.23+, August 2019, you might use git restoreinstead

注意:对于 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.cdoes 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.
--sourcecould 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 restoreis a more natural command name, and has no ambiguity.

git restore是一个更自然的命令名称,没有歧义。

回答by code_dredd

By default, git resetis 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 of git 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