“ git reset --hard hash”和“ git checkout hash”之间有区别吗?
尽管--hard
和checkout
大多数情况下都有不同的用法,但我看不出两者之间有什么区别。
可能没有人会不厌其烦地添加--hard
选项来执行基本checkout
可以执行的操作。
也许您会看到历史的方式有所不同?
这个答案大部分来自我对上一个问题的回答:git reset用普通英语。
两者有很大的不同。 它们导致索引和工作树的状态相同,但结果历史记录和当前分支不同。
假设您的历史记录如下所示,当前已检出master分支:
- A - B - C (HEAD, master)
并且运行HEAD
。您将获得以下信息:
- A - B (HEAD, master) # - C is still here, but there's no
# branch pointing to it anymore
如果也使用HEAD
或B
,则实际上会获得这种效果-唯一的区别是工作树和索引会发生什么。 在C
案例中,工作树和索引匹配D
。
现在,假设您改为运行HEAD
。 你会得到这个:
- A - B (HEAD) - C (master)
您最终处于分离的HEAD状态。 HEAD
,工作树,索引全部匹配B
,与硬重置相同,但是master分支留在了C
。如果此时进行新的提交D
,您会得到的,这可能不是您所需要的 想:
- A - B - C (master)
\
D (HEAD)
因此,您可以使用checkout来签出该提交。 您可以摆弄它,做自己喜欢的事,但是您已经把分支留在了后面。 如果您也希望移动分支,请使用reset。
如果Git随附的文档对您没有帮助,请参阅Mark Lodato撰写的《 Visual Git参考》。
特别是如果您要比较git reset --hard master~3
和git reset --hard <non-branch>
(热链接):
(来源:github.com)
请注意,对于git reset --hard master~3
,您会留下DAG修订的一部分-任何分支都不会引用某些提交。 那些(默认情况下)被reflog保护30天; 他们最终将被修剪(删除)。
git reset X
将分支引用设置为给定的哈希,并选择使用topic2
将其检出。
git reset X
将工作树设置为给定的哈希值; 除非哈希是分支名称,否则您将以一个独立的头结尾。
最终,git处理了三件事:
working tree (your code)
-------------------------------------------------------------------------
index/staging-area
-------------------------------------------------------------------------
repository (bunch of commits, trees, branch names, etc)
默认情况下git reset X
仅更新索引和工作树,并且可以选择更新存储库中的某些内容(使用topic2
选项)
git reset X
默认情况下仅更新存储库和索引,以及可选的工作树(带有topic2
选项)
您可以这样考虑存储库:
HEAD -> master
refs:
master -> sha_of_commit_X
dev -> sha_of_commit_Y
objects: (addressed by sha1)
sha_of_commit_X, sha_of_commit_Y, sha_of_commit_Z, sha_of_commit_A ....
git reset X
处理分支引用所指向的内容。
假设您的历史记录如下:
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic2][topic3]
请记住,分支只是在您提交时自动前进的名称。
因此,您具有以下分支:
master -> Q
dev -> Q
topic1 -> G
topic2 -> W
topic3 -> W
您当前的分支是git reset X
,也就是说,HEAD指向topic2。
HEAD -> topic2
然后,git reset X
会将名称topic2
重置为指向X; 这意味着,如果您在分支topic2上进行提交P,则情况将如下所示:
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic3]
\
P [topic2]