"git reset --hard hash"和"git checkout hash"之间有区别吗?

e-s*_*tis 43 git git-checkout git-reset

虽然resetcheckout具有不同用途的大部分时间,我看不出有什么区别在这两个之间.

可能有一个或任何人都--hard不愿意添加一个选项来做一些基本的checkout事情.

也许你会看到历史的方式有所不同?

Cas*_*bel 57

这个答案主要是从我对上一个问题的回答中引用的:git reset in plain english.

两者非常不同.它们导致索引和工作树的状态相同,但生成的历史记录和当前分支不同.

假设您的历史记录如下所示,当前已检出主分支:

- A - B - C (HEAD, master)
Run Code Online (Sandbox Code Playgroud)

并在运行git reset --hard B.你会得到这个:

- A - B (HEAD, master)      # - C is still here, but there's no
                            # branch pointing to it anymore
Run Code Online (Sandbox Code Playgroud)

如果您使用--mixed或实际使用,您实际上会得到这种效果--soft- 唯一的区别是您的工作树和索引会发生什么.在这种--hard情况下,工作树和索引匹配B.

现在,假设你跑了git checkout B.你会得到这个:

- A - B (HEAD) - C (master)
Run Code Online (Sandbox Code Playgroud)

你最终处于一个独立的HEAD状态.HEAD,工作树,索引全部匹配B,与硬重置相同,但主分支留在了C.如果你D在这一点上做了一个新的提交,你会得到这个,这可能不是你想要的:

- A - B - C (master)
       \
        D (HEAD)
Run Code Online (Sandbox Code Playgroud)

所以,你使用checkout来检查那个提交.你可以摆弄它,做你喜欢的事,但你已经离开了你的分支.如果您希望分支也移动,则使用重置.

  • 像往常一样+1.这个帖子(http://marc.info/?l=git&m=120955970704567&w=2)也增加了一个副作用:如果你正处于合并的中间(例如,当存在合并冲突时,或者在`git merge之后 - -no-commit`),`git reset --hard`忘记了合并,但`git checkout -f`没有; 因此,后者之后的`git commit`会创建一个合并提交,这通常不是你想要的. (6认同)

Jak*_*ski 14

如果Git提供的文档对您没有帮助,请查看Mark Lodato的A Visual Git Reference.

特别是如果你要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的一部分 - 某些提交未被任何分支引用.通过reflog保护(默认)30天; 他们最终会被修剪(删除).


has*_*sen 6

git-reset hash设置对给定哈希的分支引用,并可选择将其检出--hard.

git-checkout hash将工作树设置为给定的哈希值; 除非哈希是一个分支名称,否则你最终会得到一个分离的头.

最终,git处理3件事:

                   working tree (your code)
-------------------------------------------------------------------------
                     index/staging-area
-------------------------------------------------------------------------
      repository (bunch of commits, trees, branch names, etc)
Run Code Online (Sandbox Code Playgroud)

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 ....
Run Code Online (Sandbox Code Playgroud)

git-reset 操纵分支引用指向的内容.

假设您的历史记录如下:

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic2][topic3]
Run Code Online (Sandbox Code Playgroud)

请记住,分支只是在您提交时自动前进的名称.

所以你有以下分支:

 master -> Q
 dev -> Q
 topic1 -> G
 topic2 -> W
 topic3 -> W
Run Code Online (Sandbox Code Playgroud)

而你当前的分支就是topic2HEAD指向topic2.

HEAD -> topic2
Run Code Online (Sandbox Code Playgroud)

然后,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]
Run Code Online (Sandbox Code Playgroud)