“git reset --hard hash” 和 “git reset --hard hash” 之间有区别吗?和“git checkout 哈希”?

发布于 2024-08-27 05:15:31 字数 189 浏览 9 评论 0原文

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

可能有人或没有人愿意添加一个 --hard 选项来完成基本的 checkout 可以做的事情。

也许你们看待历史的方式有所不同?

While reset and checkout have different usages most of the time, I can't see what difference there is between these two.

There probably is one or nobody would have bothered adding a --hard option to do something the basic checkout can do.

Maybe there is a difference is the way you will see the history?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我的痛♀有谁懂 2024-09-03 05:15:31

这个答案主要引用自我对上一个问题的回答: 用简单的英语重置 git

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

假设您的历史记录如下所示,当前已签出 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

如果你也使用 --mixed--soft ,你实际上会得到这样的效果 - 唯一的区别是你的工作树和指数。在 --hard 情况下,工作树和索引与 B 匹配。

现在,假设您改为运行 git checkout B 。你会得到这样的结果:

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

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

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

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

This answer is mostly quoted from my answer to a previous question: git reset in plain english.

The two are very different. They result in the same state for your index and work tree, but the resulting history and current branch aren't the same.

Suppose your history looks like this, with the master branch currently checked out:

- A - B - C (HEAD, master)

and you run git reset --hard B. You'll get this:

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

You'd actually get that effect if you use --mixed or --soft too - the only difference is what happens to your work tree and index. In the --hard case, the work tree and index match B.

Now, suppose you'd run git checkout B instead. You'd get this:

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

You've ended up in a detached HEAD state. HEAD, work tree, index all match B, same as with the hard reset, but the master branch was left behind at C. If you make a new commit D at this point, you'll get this, which is probably not what you want:

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

So, you use checkout to, well, check out that commit. You can fiddle with it, do what you like, but you've left your branch behind. If you want the branch moved too, you use reset.

段念尘 2024-09-03 05:15:31

如果 Git 提供的文档对您没有帮助,请查看可视化 Git 参考 马克·洛达托。

特别是如果您将 git checkoutgit reset --hard (热链接)进行比较:

git checkout master~3< /a>
(来源:
github.com

git reset --hard master~3

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

If documentation provided with Git doesn't help you, take a look at A Visual Git Reference by Mark Lodato.

In particular if you are comparing git checkout <non-branch> with git reset --hard <non-branch> (hotlinked):

git checkout master~3
(source: github.com)

git reset --hard master~3

Note that in the case of git reset --hard master~3 you leave behind a part of DAG of revisions - some of commits are not referenced by any branch. Those are protected for (by default) 30 days by reflog; they would ultimately be pruned (removed).

古镇旧梦 2024-09-03 05:15:31

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

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

最终,git 处理三件事:

                   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]

git-reset hash sets the branch reference to the given hash, and optionally checks it out, with--hard.

git-checkout hash sets the working tree to the given hash; and unless hash is a branch name, you'll end up with a detached head.

ultimately, git deals with 3 things:

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

git-checkout by default just updates the index and the working tree, and can optionally update something in the repository (with the -b option)

git-reset by default just updates the repository and the index, and optionally the working tree (with the --hard option)

You can think of the repository like this:

 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 manipulates what the branch references point to.

Suppose your history looks like this:

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic2][topic3]

Keep in mind that branches are just names that advance automatically when you commit.

So you have the following branches:

 master -> Q
 dev -> Q
 topic1 -> G
 topic2 -> W
 topic3 -> W

And your current branch is topic2, that is, the HEAD points to topic2.

HEAD -> topic2

Then, git reset X will reset the name topic2 to point to X; meaning if you make a commit P on branch topic2, things will look like this:

           T--S--R--Q [master][dev]
          / 
   A--B--C--D--E--F--G [topic1]
                   \
                    Z--Y--X--W [topic3]
                           \
                            P [topic2]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文