如何在 Git 中找到向后合并?

Posted

技术标签:

【中文标题】如何在 Git 中找到向后合并?【英文标题】:How to find a backwards merge in Git? 【发布时间】:2020-02-05 17:49:11 【问题描述】:

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

    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?

【问题讨论】:

【参考方案1】:

因为“向后合并”的想法并不是 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 的脚本。如果第一个(最近的)提交返回 false,则没有向后合并;否则,最后一次返回 true 的提交是向后合并。

【讨论】:

以上是关于如何在 Git 中找到向后合并?的主要内容,如果未能解决你的问题,请参考以下文章

在 Mercurial 上退出向后合并

gitlib还原合并请求后如何再次合并

你如何在 Git 中合并两个文件?

如何在 git 中获取最后一个合并的分支名称

在idea中git合并分支报错,请问如何解决

如何在Git中手动合并所有文件?