第二次尝试从分支合并到主分支时发生Git冲突

第二次尝试从分支合并到主分支时发生Git冲突,git,merge,git-merge,git-merge-conflict,Git,Merge,Git Merge,Git Merge Conflict,考虑到以下git网络和流量: feature-foo _._._2_._._ / \ master __1__/__._.3____._._\___4__5_________7_ (now: 1.1.0-SNAPSHOT) \ release-1.0.x \___.__._._.__6__._._.____ (now: 1.0

考虑到以下git网络和流量:

feature-foo        _._._2_._._
                  /           \
master      __1__/__._.3____._._\___4__5_________7_  (now: 1.1.0-SNAPSHOT)
                        \         
release-1.0.x            \___.__._._.__6__._._.____  (now: 1.0.1-SNAPSHOT)
多次执行以下操作:

  • master
    的版本升级到
    1.0.0-SNAPSHOT
  • 删除
    featurefoo
    分支中的
    A.java
  • 分支
    release-1.0.x
    ,将
    master
    的版本升级到
    1.1.0-SNAPSHOT
    ,以进行下一个版本的开发
  • B.java
    修改为
    B'.java
    仅在
    master
  • 手动合并
    release-1.0.x
    返回到
    master
    git merge
    不通过GitLab MR)
  • release-1.0.x
    的版本升级到
    1.0.0
    ,并对其进行标记,然后再次升级到
    1.0.1-SNAPSHOT
  • 第二次尝试将
    release-1.0.x
    合并回
    master
    失败,且版本分支最近发生了更改
    • 3
      6
      是通过
      /tmp
      上的bash脚本完成的,带有完整的
      git克隆
    • 5
      7
      在单独的
      /path/to/tmp
      上使用完整的
      git克隆
    • 功能foo
      已合并回主控(接受MR)
    • master
      at
      1
      had
      A.java
    • release-1.0.x
      仍然有
      A.java
      (这很好)
    • release-1.0.x
      仍然有
      B.java
      (这很好)
    • 一些文件被合并回
      5
      ,不包括
      A.java
      B.java
    对于步骤
    5
    7
    我都做了

    git clone ...
    git checkout release-1.0.x
    git checkout master
    git merge --no-ff --no-commit release-1.0.x
    
    successfully on 5:
    
    git add .
    git commit
    git push
    
    奇怪的是,在第二次尝试中,我遇到了大量的冲突,包括A.java(它试图将其交给master)和
    B.java
    (它试图将过时的from release分支合并到master并产生冲突)

    我的问题是:

    • 我是不是遗漏了什么(明显的)
    • 将long live release分支合并回master的过程是否正确(例如,每月两次)
    • 为什么我现在有冲突而不是第一次尝试
    编辑


    版本在添加到
    .gittributes
    中的
    pom.xml
    s中进行碰撞,以使用我们的策略进行处理。

    6之后,master和release都对其版本进行碰撞。您并没有提到碰撞版本的确切含义,但我假设相同文件中的相同行已被编辑到两个分支中,这将导致冲突。至于为什么a.java和b.java突然发生冲突,我的猜测是它们(或它们的路径)是在6期间编辑的。

    这确实应该是一个注释,但我没有足够的空间放在一个文件中,也无法很好地格式化内容

    对于标记为
    7
    的两个提交,您绘制的提交图只有一个合并基,可能根本没有标记(发布版-1.0.x的提示提交)。合并基提交是您标记为
    3
    的提交。但在你的文本中,你说:

    一些文件被合并回
    5

    然而,在任何地方都没有连接
    5
    的额外图形线:
    5
    看起来像是一个普通的非合并提交,其(单个)父级是commit
    4
    。因此,我不确定您是否过度简化了图形

    最简单的方法是让Git在合并出现问题时告诉您Git认为合并基础是什么。如果您当前在branch
    master
    上,并且即将运行
    git merge release-1.0.x
    ,您可以使用以下命令查看git认为哪些提交是合并基础(可能是复数):

    输出是一些幸运的提交散列ID,只有一个ID是合并的基础。(如果您已经进行了合并,则如果提交是合并前的当前提交,则将
    HEAD
    替换为哈希ID。同样,如果版本-1.0.x自合并后已移动,则将其替换为合并中提交的哈希ID。)

    如果有多个合并基,则会有一点问题。Git的默认值是使用
    -s递归的
    合并策略合并合并基。此合并的结果是一个新的“虚拟提交”,然后将其作为最终合并的合并基础。虽然您可以(递归地)手动执行我将要描述的操作,但它会变得非常痛苦:除其他外,您可能必须为每个潜在的虚拟提交进行真正的提交。但是对于任何luck1,都只有一个合并基,可能它毕竟是提交
    3

    无论如何:

    我遇到了大量的冲突,包括
    A.java
    B.java

    要查看合并将做什么,以及为什么它认为这两个文件需要合并,请运行:

    git diff -M <merge-base-commit> <tip-1> > /tmp/merge-input-1
    git diff -M <merge-base-commit> <tip-2> > /tmp/merge-input-2
    
    在差异2中,我们看到:

    -another
    +another
    
    这些需要组合,所以Git将调用您的合并驱动程序。(更准确地说,Git检查三个散列ID:基本文件的散列、tip#1中文件的散列和tip#2中文件的散列。如果这三个ID不同,Git将调用合并驱动程序。)

    另一方面,可能只有tip#1或只有tip#2会更改文件(因此它在基础中与在另一个tip中相同)。在这种情况下,Git会在不运行驱动程序的情况下获取任何一个已更改的文件。对于像
    pom.xml
    这样的文件,这通常是您想要的!(对于版本编号,这可能不是您想要的,但可能您还有另一个步骤来处理。)

    如果Git确实调用了您的驱动程序,那么这当然取决于您的驱动程序。这就是“保留我们的”和“git合并文件——我们的”的不同之处。前者更像是
    -s ours
    策略:它完全忽略基本文件和其他/他们的文件。后者使用“两种改变都接受,但如果发生冲突,支持我们”的解决方法,并且是
    -this
    +that
    
    -another
    +another