如何改变一系列分支机构?

时间:2013-11-08 13:42:05

标签: git rebase

假设我们有以下修订图:

A-B (master)
   \
    C (feature-a)
     \
      D (feature-b) [depends on feature a]
       \
        E (feature-c) [depends on feature b]

然后修改master以跟随commit F是否有任何简单的方法可以将E重新定位到F(主要),以便分支feature-afeature-bfeature-c最终如下:

A-B-F (master)
     \
      C' (feature-a)
       \
        D' (feature-b)
         \
          E' (feature-c)

在现实世界中,每个功能之间显然存在多个补丁,因此在手动重新连接分支到重新定位的历史记录是繁琐且容易出错的工作。我知道我可以使用简单的EE'重新定义为git checkout feature-c && git rebase master,但会使分支feature-afeature-b指向提交C和{ {1}}代替DC'。 Rebase应该拥有移动所有分支的所有信息,对吗?

4 个答案:

答案 0 :(得分:2)

git没有内置任何功能,但它确实可以编写脚本。

您需要做的是:

  • 确定要重新定位的分支(此处为feature-afeature-bfeature-c)。
  • 对于每个分支,确定哪些待重组的分支“包含”它们(让我们称之为“是前任”)。分支XY的前身,如果YX的后代(并选择此处处理/断开关系 - 两个分支名称标识同一承诺)。在这种情况下,feature-afeature-bfeature-c的前身,而feature-bfeature-c的前身(仅限)。保存前辈的“距离返回”值(追逐父链的距离)。
  • 执行拓扑排序。 (实际上你可以作弊而且只是找到叶子。如果你通过某种方法选择分支名称而不是观察提交DAG,你只需要循环检查。)
  • 对于每个叶子(在这种情况下只是feature-c):
    • 重新启动它。
    • 对于这片叶子的每个前身,将它从现在的任何地方移动到新的叶尖上的N-parents-back。

(就是这样,一切都完成了。)

使用git merge-base --is-ancestor(成对)或git branch --contains进行前置测试很容易(一次性,但需要过滤掉非重新分支的分支)。找到“N back”值有点棘手,但我相信可以通过git rev-list传送到wc -l来完成。

编辑:我看到链接的答案(在上面的评论中)使用了类似的算法 - 包括拓扑排序/周期性检查,因为分支选择方法不是“从提交DAG中获取” - 但需要更多工作,根据指示明确重新定位每个分支。如果你在DAG工作,那么leaf rebase已经完成了所有的工作,并且可以简单地重新标记前辈,正如我所指出的那样。

答案 1 :(得分:1)

试试这个:

git checkout featurea
git rebase
git branch --contains (sha1 of your old commit C) |xargs -n 1 git rebase --onto (sha1 of your new commit C') (sha1 of your old commit C)

答案 2 :(得分:0)

我目前能想到的最好的方法是一个接一个地改变:

git rebase --onto master B feature-a
git rebase --onto feature-a C feature-b
git rebase --onto feature-b D feature-c

但是无论何时遇到这样的问题,请再想一想,如果你真的想要这样,并了解后果。

答案 3 :(得分:0)

应该很简单。在E上重新F会使整个分支机构提交CD

git checkout B
…
git commit -m 'F'
git checkout E
git rebase F