“与”之间有区别吗;git reset——硬哈希;及;git签出哈希“;?
虽然“与”之间有区别吗;git reset——硬哈希;及;git签出哈希“;?,git,git-checkout,git-reset,Git,Git Checkout,Git Reset,虽然reset和checkout在大多数情况下有不同的用法,但我看不出这两者之间有什么区别 可能有一个或者没有人会费心添加一个--硬选项来做一些基本签出可以做的事情 也许你看待历史的方式有所不同?这个答案主要是从我对前一个问题的回答中引用的: 这两个是非常不同的。它们导致索引树和工作树处于相同的状态,但生成的历史记录和当前分支不同 假设您的历史记录如下所示,主分支当前已签出: - A - B - C (HEAD, master) 然后运行git reset--hard B。您将得到以下结果:
reset
和checkout
在大多数情况下有不同的用法,但我看不出这两者之间有什么区别
可能有一个或者没有人会费心添加一个--硬选项来做一些基本签出可以做的事情
也许你看待历史的方式有所不同?这个答案主要是从我对前一个问题的回答中引用的:
这两个是非常不同的。它们导致索引树和工作树处于相同的状态,但生成的历史记录和当前分支不同
假设您的历史记录如下所示,主分支当前已签出:
- A - B - C (HEAD, master)
然后运行git reset--hard B
。您将得到以下结果:
- A - B (HEAD, master) # - C is still here, but there's no
# branch pointing to it anymore
- A - B (HEAD) - C (master)
如果您也使用--mixed
或--soft
,您实际上会得到这种效果,唯一的区别是工作树和索引会发生什么变化。在--hard
情况下,工作树和索引匹配B
现在,假设您运行的是git checkout B
。你会得到这个:
- A - B (HEAD, master) # - C is still here, but there's no
# branch pointing to it anymore
- A - B (HEAD) - C (master)
你最终处于一种超然的状态<代码>头
,工作树,索引全部匹配B
,与硬重置相同,但主分支被留在C
处。如果此时进行新的提交D
,您将得到以下结果,这可能不是您想要的:
- A - B - C (master)
\
D (HEAD)
所以,您使用checkout来检查提交。你可以摆弄它,做你喜欢做的事,但是你把你的树枝落在了后面。如果您也希望移动分支,可以使用reset。如果Git提供的文档对您没有帮助,请参阅Mark Lodato的文章
特别是,如果您将git checkout
与git reset--hard
(热链接)进行比较:
(来源:)
请注意,在git reset--hard master ~3
的情况下,您会留下一部分DAG修订版—某些提交没有被任何分支引用。reflog(默认情况下)会对其进行30天的保护;它们最终将被删除。git reset hash
将分支引用设置为给定的hash,并可以选择使用--hard
将其签出
git checkout hash
将工作树设置为给定的hash;除非hash是一个分支名称,否则最终会得到一个分离的头
最终,git处理3件事:
working tree (your code)
-------------------------------------------------------------------------
index/staging-area
-------------------------------------------------------------------------
repository (bunch of commits, trees, branch names, etc)
git checkout
默认情况下只更新索引和工作树,并且可以选择更新存储库中的内容(使用-b
选项)
默认情况下,git reset
只更新存储库和索引,还可以选择更新工作树(使用--hard
选项)
您可以这样看待存储库:
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 ....
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic2][topic3]
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic3]
\
P [topic2]
git reset
操作分支引用指向的内容
假设您的历史如下所示:
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 ....
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic2][topic3]
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic3]
\
P [topic2]
请记住,分支只是在提交时自动前进的名称
因此,您有以下分支:
master -> Q
dev -> Q
topic1 -> G
topic2 -> W
topic3 -> W
您当前的分支是topic2
,也就是说,头部指向topic2
HEAD -> topic2
然后,git reset X
将重置名称topic2
以指向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 ....
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic2][topic3]
T--S--R--Q [master][dev]
/
A--B--C--D--E--F--G [topic1]
\
Z--Y--X--W [topic3]
\
P [topic2]
我在对您以前的一个问题的回答的更新中介绍了这一点-请看顶部附近的ascii艺术,特别是其中的“题外话:…”(尽管我非常希望在这里重新回答,但我确实认为您可以在这里发布您的回答,并从中获得代表性。如果有人搜索这个特定的知识,他将找不到另一个职位。这一个目标是一个非常具体的主题,它应该有一个单独的页面。顺便说一句,看来你是我的Git导师:-)harigato,senseï!但我明白了,不同的是重置会移动分支,而不是签出。@e-satis:是的,你说得对。答案就在这里,如果可以的话,我会收回我的投票!不客气,我很高兴能够利用我在工作之外积累的所有知识。请照常参阅+1。这个线程()也增加了一个副作用:如果你处于合并的中间(例如,当有合并冲突,或者在代码> Git合并-没有提交< /代码>)时,<代码> Git重置-硬< /代码>忘记合并,但是<代码> Git Cuff-F不;因此,在后者之后的git提交将创建一个合并提交,这通常不是您想要的。