如何重新分配一系列分支? [英] How to rebase a series of branches?

查看:97
本文介绍了如何重新分配一系列分支?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下修订图:

  AB(主)
\
C (feature-a)
\
D(feature-b)[取决于特征a]
\
E(特征-c)[取决于特征b]

然后修改master以跟踪commit F 是否有简单的方法将 E 转换为 F (master),以便分支 feature-a feature-b feature-c 全部结束如下:

  ABF(master)
\
C'(feature-a)

D'(feature-b)
\
E'(feature-c)



在现实世界中,每个功能之间显然存在多个补丁,因此需要手动重新连接分支重新设计历史是乏味且容易出错的工作。我知道我可以通过一个简单的 git checkout feature-c来将 E 转换为 E' &安培;&安培; git rebase master 但是会留下分支 feature-a feature-b 指向提交 C D 而不是 C' d'。 Rebase应该有所有的信息来移动所有的分支,对吗?

解决方案

没有内置的git来执行此操作,但它的确是脚本功能。



您需要做的是:


  • 确定要重新设计的分支(这里 feature-a feature-b feature-c )。

  • 对于每个分支,确定哪些待重新分支包含它们(我们称之为是前任 )。如果 Y 是一个分支 X ,则前者是 Y X 的后代(并且在这里选择一些用于处理/断开的东西 - 带有两个标识相同提交的分支名称)。在这种情况下, feature-a feature-b feature- c ,而 feature-b feature-c (仅)的前身。保存前辈的距离后退值(追逐母链的距离)。

  • 执行拓扑排序。 (实际上你可以作弊并找到叶子,如果你通过除了观察提交DAG之外的其他方法选择分支名称,你只需要一个循环检查。)
  • 对于每个叶子例如: feature-c ):

    • 重新使用它。

    • 这片叶子的前身,将它从现在的任何地方移到新的叶子尖端的N-parents-back。




(就这样,全部完成了。)

使用 git merge-base - (成对)或 git branch --contains (整体而言,但需要过滤非重新分支的分支)。找到N back值有点棘手,但我相信可以通过 git rev-list 管道传输给 wc -l <​​/ code>,例如。

编辑:我看到链接的答案(在上面的评论中)使用了类似的算法 - 包括拓扑排序/循环检查,因为分支选择方法不是从提交DAG中提取 - 但有了更多的工作,按照指示明确重新分配每个分支。如果你是从DAG工作的话,那么叶基金会已经完成了所有的工作,而前人可以简单地重新贴上标签,正如我注意到的那样。

Suppose we have the following revision graph:

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

And master is then modified to follow with commit F. Is there any simple way to rebase E onto F (master) so that branches feature-a, feature-b and feature-c all end up as follows:

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

?

In real world situations there are obviously multiple patches between each feature so re-attaching branches in-between manually to rebased history is tedious and error prone job. I know that I can rebase E to E' with a simple git checkout feature-c && git rebase master but that leaves branches feature-a and feature-b pointing to commits C and D instead of C' and D'. Rebase should have all the info to move all the branches, right?

解决方案

There's nothing built in to git to do this, but it's certainly script-able.

What you need to do is:

  • Identify the branch(es) to be rebased (here feature-a, feature-b, and feature-c).
  • For each branch, determine which to-be-rebased branches "contain" them (let's call this "is a predecessor"). Branch X is a predecessor of Y if Y is a descendent of the X (and choose something here to handle/break-ties-with two branch names that identify the same commit). In this case, feature-a is a predecessor of both feature-b and feature-c, while feature-b is a predecessor of feature-c (only). Save the "distance back" values for predecessors (how far to chase parent chain).
  • Perform a topological sort. (Actually you can cheat and just find leaves. You only need a cycle-check if you pick branch names by some method other than observing the commit DAG.)
  • For each leaf (in this case just feature-c):
    • Rebase it.
    • For each predecessor of this leaf, move it from wherever it is now, to N-parents-back from the new leaf tip.

(That's it, all done.)

Predecessor testing is easy with git merge-base --is-ancestor (pairwise) or git branch --contains (en masse, but requires filtering away non-rebased branches). Finding the "N back" value is a little trickier, but I believe can be done with git rev-list piped to wc -l, for instance.

Edit: I see that the linked answer (in comment above) uses a similar algorithm—including topo-sort/cyclicality-checking, needed because the branch selection method is not "take from commit DAG"—but with more work, explicitly rebasing each branch as directed. If you work from the DAG, the leaf rebase has done all the work, and the predecessors can simply be relabeled, as I noted.

这篇关于如何重新分配一系列分支?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆