如何在Git中更改分支点?

4
假设我在Git仓库中有以下结构:
          C'---D'---E'---F'    (dev)
        / 
A---B---C---D---E---F       (master)

我希望将 C' 合并到主分支,并将分支点改变为 C',即我想将上述内容转化为:
              D'---E'---F'     (dev)
             / 
A---B---C---C'---D---E---F  (master)

我认为我应该使用挑选和变基的组合,但是我对如何确切操作感到困惑。 我应该执行哪个操作序列?
          G---H---I---J   (dev)
         / 
A---B---C---D---E---F     (master)

与预期的结果相关:

              H---I---J    (dev)
             / 
A---B---C---G---D---E---F  (master)

1
同字母提交之间有什么关系?(例如 CC')这些是相同版本的变基,还是还原操作?或者其他什么操作?(另外,你期望的结果是不可能实现的,因为无论如何 D 都将始终具有 C 作为其父提交) - Romain Valeri
@RomainValeri CC' 的父级(也是 D 的父级)。你提到的 D 总是需要有 C 作为其父级的观点是有道理的。因此,也许我需要在图表中用某个与 D 相同但其父级为 C'D'' 替换 D - MikeL
你没有回答我的问题。当然,CC'的父节点,你的模式已经告诉我们了。我会换一种说法:如果所有提交都只是提交,为什么你没有用不同的字母命名它们?我们通常使用A'来表示A的变基版本或反向版本。 - Romain Valeri
@RomainValeri 很抱歉,我误解了你的问题。 DD'EE' 等之间没有关系。(只有 CC' 的父级。) 我的提交标签很令人困惑,而且我不知道有关变基提交的约定。 - MikeL
不是有意冒犯,只是想帮助您避免对回答者产生错误的假设。如果您觉得需要的话,我建议您重新命名您的模式。 - Romain Valeri
3个回答

3
您的新图表的简短答案是,您需要使用以下命令在G上进行变基操作:
git checkout master
git rebase <commit_id_G>

较长的答案是,您难以看到这一点,因为您认为master是“主”分支,而dev是“支线”。但是,这些分支名称只是标签,您可以将它们中的任何一个视为“主”分支。由于master是我们实际想要更改的分支,因此我们可以像这样重新绘制图表:
          H---I---J        (master)
         / 
A---B---C---D---E---F---G  (dev)

带有相关的预期结果:
              H'--I'--J'    (master)
             / 
A---B---C---D---E---F---G   (dev)

希望这里更容易理解,我们只需要将masterC变为这个新的D进行变基。

这应该是 git rebase hash-of-D(而不是 G 的哈希),但除此之外,这是正确的(并且已经得到了赞同)。请注意,原始的 H-I-J 链仍然存在于存储库中(通过 ORIG_HEAD 暂时找到,并且默认情况下通过 master 的 reflog 至少保留 30 天)。我喜欢用名称 H'-I'-J' 绘制新提交,以表示尽管我们将它们用作原始的 H-I-J 链,但它们实际上是具有新的、不同的哈希 ID 的新提交。 - torek
@torek,我指的是第二个图中OP的G。确实有点令人困惑。不过我会按照你的建议重新制作我的第二个图,并加上质数符号。 - seumasmac
谢谢!看来我的关于rebase的理解完全错误了。请问有没有人能够友好地介绍一下git的好教程呢?(我主要是在单个分支上使用git进行版本控制,有点像svn的替代品,但我知道git还有很多其他功能,很想学习它们。) - MikeL

2

你只需要将 master 分支变基到 G 分支上:

git checkout master
git rebase <id-of-G>

这将重写所有在master中找到的提交,这些提交在G中找不到,并将它们叠加在G之上。不需要使用cherry-pick。您的dev分支将保持不变。


-2

您需要执行以下操作:

记录这些提交的哈希引用:CC'DEF。然后:

  1. git checkout master
  2. git reset --hard C
  3. git cherry-pick C'
  4. git checkout dev
  5. git rebase -i master(交互式变基以摆脱C')
  6. git checkout master
  7. git cherry-pick D
  8. git cherry-pick E
  9. git cherry-pick F

使用--force推送两个分支以完成。

如果您不熟悉git,我不建议您这样做,但如果绝对需要这样做,那么这就是我会采取的方法。

您始终可以选择这条路线

                           D'---E'---F'     (dev)
                          / 
A---B---C---D---E---F---C'  (master)

只需 cherry-pick C' 然后将您的 dev 分支重新基于 master 进行变基。这将是最简单的解决方案。


这是一种复杂的方法,没有任何理由在“dev”上重写历史记录。 - Calum Halpin
从原始帖子来看,他想在两个分支上重写历史记录。他想从dev中取出一些内容,放到master的中间,然后将dev从被放入master的提交中rebase出来。 - Felipe Cabargas
他的图表显示了dev完全相同的历史记录。它在不同的点上分支出master,但那是因为master已经改变了。 - Calum Halpin
我想将 C' 合并到 master 分支,并将分支点更改为 C'。他的原始图表清楚地显示了这一点。不确定为什么每个人都在忽略原始问题。正如我所说,我个人不会这样做,但我相信他一定有自己的理由。 - Felipe Cabargas
“分支点”就是两个分支历史开始分歧的地方。将 master 单独变基到 C'/G 会改变它,因为现在 master 含有该提交。无论如何,dev 的历史记录将是 A -> B -> C -> G -> H -> I -> J,没有必要变基/重写这些提交。这就是我们“忽略”原始问题中那部分的原因。 - Calum Halpin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接