46

虽然大多数reset时候checkout都有不同的用法,但我看不出这两者之间有什么区别。

可能有人或没有人会费心添加一个--hard选项来做一些基本checkout可以做的事情。

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

4

3 回答 3

64

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

两者非常不同。它们为您的索引和工作树生成相同的状态,但生成的历史记录和当前分支不一样。

假设您的历史记录如下所示,并且当前已签出 master 分支:

- 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

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

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

- A - B (HEAD) - C (master)

您最终处于分离的 HEAD 状态。HEAD, 工作树, 索引都匹配B, 与硬重置相同, 但主分支留在了C. 如果此时你进行新的提交D,你会得到这个,这可能不是你想要的:

- A - B - C (master)
       \
        D (HEAD)

因此,您使用 checkout 来检查该提交。你可以摆弄它,做你喜欢的事,但你已经把你的分支抛在脑后了。如果您希望分支也移动,请使用重置。

于 2010-03-29T22:10:19.170 回答
15

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

特别是如果您git checkout <non-branch>git reset --hard <non-branch>(热链接)进行比较:

git checkout master~3
(来源:github.com

git reset --hard master~3

请注意,如果git reset --hard master~3您留下部分 DAG 修订版 - 任何分支都不会引用某些提交。这些受reflog保护(默认情况下)30天;它们最终将被修剪(移除)。

于 2010-03-30T00:34:52.773 回答
6

git-reset hash将分支引用设置为给定的散列,并可选择将其签出,使用--hard.

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

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]
于 2010-03-30T05:19:45.763 回答