【问题标题】:Git: What happens to a branch after a master resetGit:主重置后分支会发生什么
【发布时间】:2019-07-29 17:34:48
【问题描述】:

假设我有一个 master 分支,其中有一些提交我想保留以供以后的文档和参考,但将它们从 master 中删除(因为我希望 master 处于与上游 repo 相同的状态)。

我现在的方法是,

  1. 从当前主状态创建一个新分支
  2. 将 master 重置(--hard)到上游 repo 中也存在的状态

现在,我的问题是:

  • 从 master 中删除引用提交时,新分支会发生什么情况?
  • 或者我对如何引用分支的理解完全错误。

通常分支以以下方式显示,其中(据我了解)D 是新分支的基础。

A - B - C - D    (master)
             \
                 (new branch)

分支是自动“重新定位”还是你怎么称呼它? 会是这个样子吗?

A - B         (master)
     \
      C - D   (new branch)

最后也是最普遍的问题:

  • 我在新分支和reset --hard master 分支中保持状态的方法是实现我的目标的正确方法,即无需我的提交 (@987654326 @ 和 D) 合并了吗?

【问题讨论】:

  • 提交是不可变的。您通常会在 rebase 后看到 A-B-C-D 更改为 A-B-C'-D',以反映尽管提交 CC' 在源代码树中引入了相同的更改,但它们是不同的提交。

标签: git git-reset


【解决方案1】:

分支不会“发生”任何事情,因为 git 中的分支只是一个轻量级的、可移动的、一次性的指针。 提交是真实的。

是的,总体计划很好,创建一个新分支来保留最近的提交,将 master 重置到它应该的位置(我猜是origin/master),然后这个 ref 在你的 C 上, D 提交将允许他们永久保留

如果不创建分支,它们最终会被垃圾回收,即使它们会在 reflog 中停留一段时间。

而且不,如果您遵循您宣布的行动方案,您的 C 和 D 提交不会合并到您的上游 master。去吧。

【讨论】:

    【解决方案2】:

    从 master 中删除引用提交时,新分支会发生什么情况?

    什么都没有。

    您的问题似乎是基于对分支是什么的误解。分支是一种 ref - 与其他 ref 的不同之处仅在于 git 有一些关于分支指向和移动方式的约定。 ref 是指向 commit[1] 的指针。

    重置master 时,您只是更改了master 引用的指针,使其停止指向D 并开始指向B。这不会以任何方式影响作为 new branch 引用的指针。

    提交CD 仍然存在,并且也不受重置master 的影响。只是 master 不再指向可以“到达”它们的地方(而在 D 可以到达之前,因为它是 master 所指向的,而 C 可以通过 D 到达s 父指针)。

    但是new branch仍然指向D,所以它仍然可以到达CD

    所以new branch 不会被重新定位或任何东西。变基是重写和替换提交,因为您希望相对于不同的起点做出与他们所做的相同的更改。这不是在这里发生的。它是 rebase 的提交,并且通常在 rebase 提交时,ref 会随之而来;但是当我们说“rebase a branch”时,它是“rebase some commits 当前可从分支访问,然后移动分支以指向新提交”的简写。但在这里我们不需要任何这些;我们仍然有我们原来的提交。

    “分支只是一个指针”的另一面——提交不是任何分支的“一部分”。它们独立于任何可能引用它们的分支而存在(尽管git gc 如果认为没有人知道如何再找到它们,最终会尝试处理它们)。分支指向的提交,以及可以通过父指针从那里到达的提交,据说构成了分支的历史......但就关系而言。

    所以重申和总结一下 - 重置master 只会移动一个指针。它不会更改提交,也不会影响其他分支。


    [1] 一些 refs 有时会指向提交以外的其他内容,但这对于本次讨论来说并不太重要; tl;dr - 分支是指向提交的指针,仅此而已

    【讨论】:

      【解决方案3】:

      提交链在某些东西指向它们时保持活动状态,否则直到它们被git gc 擦除,并且您的重置前/重置后拓扑图是正确的。

      【讨论】: