首页 > 解决方案 > 如何在 Git 中找到向后合并?

问题描述

我公司有发布分支。在合并回发布分支之前,必须在自己的分支中创建更改。典型的工作流程可能如下所示:

    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?

标签: gitversion-controlbranchgit-branchbranching-and-merging

解决方案


因为“向后合并”的想法不是 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

这假设对于添加到发布分支的每个合并,第一个父级是发布分支的先前提交,这通常是正确的。有一些方法可以创建不正确的合并。(最简单的是合并V1.0 另一个分支,然后快进V1.0到合并。)

如果您担心会发生这样的事情,那么您必须省略该--first-parent选项,然后您的脚本需要一种方法来整理分支拓扑。现在我假设这没有必要。

所以现在你只需要一个脚本沿着提交列表向下工作,git merge-base ...在每次提交时运行测试(),直到它找到一个测试返回错误的地方。如果第一个(最近的)提交返回 false,则没有向后合并;否则,最后一次返回 true 的提交是向后合并。


推荐阅读