“git reset –hard hash”和“git checkout hash”有区别吗?
虽然大多数时候reset
和checkout
有不同的用法,但是我看不出这两者之间有什么区别。
可能有一个,或者没有人会join一个 – --hard
选项来做一些基本的checkout
。
也许有什么不同,你会看到历史的方式?
这个答案大部分是从我对前一个问题的回答中引用的: git reset in plain english 。
这两个是非常不同的。 它们导致您的索引和工作树处于相同的状态,但生成的历史logging和当前分支不一样。
假设您的历史logging如下所示,主分支目前已经签出:
- 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
如果你使用--mixed
或者--soft
,你会得到这个效果 – 唯一的区别是你的工作树和索引会发生什么。 在这种情况下,工作树和索引匹配B
现在,假设你会运行git checkout B
你会得到这个:
- A - B (HEAD) - C (master)
你已经结束了一个分离的HEAD状态。 HEAD
,工作树,索引全部匹配B
,与硬重置相同,但主分支留在C
。 如果你现在做了一个新的提交D
,你会得到这个,这可能不是你想要的:
- A - B - C (master) \ D (HEAD)
所以,你使用checkout来检查那个提交。 你可以捣鼓它,做你喜欢的,但是你把你的分支留下了。 如果你想分支也移动,你使用重置。
如果Git提供的文档不能帮助您,请参阅Mark Lodato的“ Visual Git参考” 。
特别是如果你比较git checkout <non-branch>
和git reset --hard <non-branch>
(hotlinked):
git checkout master〜3 http://marklodato.github.com/visual-git-guide/checkout-detached.svg.png
git reset –hard master〜3 http://marklodato.github.com/visual-git-guide/reset-commit.svg.png
请注意,在git reset --hard master~3
的情况下,您会留下部分修订版的DAG – 部分提交不会被任何分支引用。 这些保护(默认)30天reflog ; 他们最终将被修剪(删除)。
git-reset hash
将分支引用设置为给定的哈希值,并且可以select使用--hard
进行检查。
git-checkout hash
将工作树设置为给定的散列值; 除非散列是一个分支的名字,否则你会得到一个分离的头。
最终,git处理3件事情:
working tree (your code) ------------------------------------------------------------------------- index/staging-area ------------------------------------------------------------------------- repository (bunch of commits, trees, branch names, etc)
git-checkout
默认只是更新索引和工作树,并且可以select更新仓库中的某些东西(带-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 ....
git-reset
操作分支引用指向的内容。
假设你的历史是这样的:
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
而你当前的分支是topic2
,也就是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]