我的公司有发行分支。更改必须先在自己的分支中创建,然后才能合并回发行分支。典型的工作流程可能如下所示:
A---F----------M------ V.1
\ / \ /
E H------L
在将更改合并到版本V.1分支之前,已在E,H和L中添加了更改。
[如果我们同时在V.2上工作,那么对V.1的任何更改也必须“合并”到V.2:
C--D
/ \
B---G--J---K---N-- V.2
/ / \ / /
/ / I--' /
/ / /
A---F----------M------ V.1
\ / \ /
E H------L
这可确保将应用于V.1的所有错误修正结转到V.2。
有时,开发人员会不小心合并到错误的发行分支。假设从V.2分支出来的提交“ I”已被向后合并到V.1:
C--D
/ \
B---G--J-------N-- V.2
/ / \ /
/ / I /
/ / \ /
A---F-------K--M------ V.1
\ / \ /
E H------L
在这种情况下,我们称K为“向后合并”。它导致V.2中的所有新功能都合并到V.1中,这非常糟糕。
发生这种情况时,我们尝试找到向后合并K,以便我们可以还原更改。不幸的是,每天要进行数百次提交,通过视觉检查图形很难找到K。
我们如何找到以编程方式向后合并K?
因为这种“向后合并”的想法并不是git所了解的,所以您需要做一些自定义脚本。 (我想想最能帮助您解决此问题的最接近的是git bisect
-但效果不佳,因为它认为它是在寻找引入某些行为的个人提交,而您想查找某些行为在哪里)合并到特定分支中。)
所以...
您需要的第一个精简版是一种测试提交是否包含来自v2
的更改的方法。您可以签出最早的v2
提交(在示例图中为B
),然后在其中创建标签
git tag v2-root
然后您可以检查一次提交以查看v2-root
是否“可达”;有几种方法,但是最直接的方法可能是
git merge-base --is-ancestor v2-root <some-commit>
接下来,您需要测试的提交列表。您可以使用git rev-list
。通常情况下,您可以使用
git rev-list --first-parent v1.0
这假定对于添加到release分支的每个合并,第一个父对象是release分支的先前提交,通常是正确的。在不正确的情况下,有多种方法可以创建合并。 (最简单的方法是将V1.0
into]合并到另一个分支,然后将V1.0
快进到合并中。)
如果担心这种情况的发生,则必须省略--first-parent
选项,然后脚本需要一种方法来整理分支拓扑。现在,我认为这是没有必要的。
所以现在您只需要一个脚本来沿提交列表进行操作,就每次提交运行测试(git merge-base ...
),直到找到一个测试返回false的脚本为止。如果第一次(最近一次)提交返回false,则不存在向后合并;否则,向后合并。否则,返回true的最后一个提交是向后合并。