【问题标题】:Git conflict on second attempt to merge from branch to master第二次尝试从分支合并到主控时发生 Git 冲突
【发布时间】:2017-10-27 23:41:08
【问题描述】:

考虑以下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)

随着时间的推移采取以下行动:

  1. master 的版本更新为1.0.0-SNAPSHOT
  2. feature-foo 分支中删除A.java
  3. 分支release-1.0.x,将master 的版本升级为1.1.0-SNAPSHOT 以进行下一个版本开发
  4. B.java 仅在 master 上修改为 B'.java
  5. 手动将release-1.0.x 合并回mastergit merge 不是通过 GitLab MR)
  6. release-1.0.x 的版本添加到1.0.0 并标记它并再次添加到1.0.1-SNAPSHOT
  7. 第二次尝试将 release-1.0.x 合并回 master 与发布分支上的最新更改失败

  • 36 是通过 /tmp 上的 bash 脚本完成的,带有完整的 git clone
  • 57 是在单独的 /path/to/tmp 上手动完成的,完整的 git clone
  • feature-foo 被合并回master(接受MR)
  • master 1A.java
  • release-1.0.x 仍然有 A.java(这很好)
  • release-1.0.x 仍然有 B.java(这很好)
  • 一些文件被合并回5 不包括 A.javaB.java

对于57 这两个步骤我都做了

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

奇怪的是,现在在第二次尝试时,我遇到了很多冲突,包括 both A.java(它试图将其转移给 master)和 B.java(它试图合并过时的将分支释放到 master 并产生冲突)。

我的问题是:

  • 我在这里遗漏了什么(很明显)吗?
  • 将长期发布分支合并回 master 的过程是否正确(例如每月两次)?
  • 为什么我现在就遇到冲突而不是第一次尝试?

编辑

版本被添加到pom.xmls 中,这些版本已添加到.gitattributes 中,以使用我们的策略进行处理。

【问题讨论】:

  • --no-commit 在提交之前中止合并,这意味着如果您之后不手动调用git commit,则不会发生合并。相反,您最终会在合并过程中进行大量未提交的更改。如果您离开它们,这些将导致各种问题。你在 5 点之后还做了什么你没有提到的事情吗?
  • @oyvind 是的,仅在 5 上我确实做到了,我在 7 上没有达到提交的地步。我会更新问题。
  • 或者更确切地说,6 和 5 发生在同一个克隆上吗?还是 6 在其他地方完成?
  • @oyvind 更新了问题。 3 和 6 是 /tmp 中各个文件夹上的纯克隆

标签: git merge git-merge git-merge-conflict


【解决方案1】:

这确实应该是一个评论,但我没有足够的空间,我也不能很好地格式化。

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

一些文件被合并回5 ...

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

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

git merge-base --all HEAD release-1.0.x

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

如果有多个合并基地,你有一点问题。 Git 使用-s recursive 合并策略的默认设置是合并合并基础。此合并的结果是一个新的“虚拟提交”,然后将其视为最终合并的合并基础。虽然您可以(递归地)手动执行我将要描述的事情,但它会变得非常痛苦:除此之外,您可能必须为每个潜在的虚拟提交进行真正的提交。但运气好的话1只有一个合并基础,也许它毕竟提交3

无论如何:

我遇到了很多冲突,包括 A.javaB.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

这里 tip-1mastertip-2release-1.0.x。当然,合并基础提交是您在上面找到的(单个)哈希 ID。

如果有问题的两个文件在所有三个提交中都存在,那么您不会因为任何重命名问题而绊倒,所以我什至不会在这里提出这些问题。


1嗯,从技术上讲,这不是运气问题。合并基础歧义只有在交叉合并时才会发生,即使那样,它们也需要具有相同的“距离”。所以产生多个merge base比较困难。


最后,还有最后一点。它最终可能很重要,但实际上并不是这里的问题。它认为:

版本在pom.xmls 中碰撞,这些版本已添加到.gitattributes 以使用我们的 策略进行处理。

没有办法在.gitattributes 中获得真正的“我们的”策略。 (甚至没有“我们的”标记。)我猜你的意思是你写了一个合并驱动程序,它本质上使用git checkout --ours当有冲突时。也有可能您编写了一个在三个输入上使用git merge-file --ours 的合并驱动程序。

这些都是微妙的不同。

首先要知道的是,您的合并驱动程序在 Git 发现冲突时运行。

当您执行上述两个git diff -M 命令时,您可以看到哪些文件 有需要合并的更改。如果与合并基础 B 相比,both 分支提示有一个不同 pom.xml,那么就需要合并一些东西。也就是说,假设在 diff #1 中我们看到:

-this
+that

在 diff #2 中我们看到:

-another
+another

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

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

如果 Git 确实 调用您的驱动程序,那么它当然取决于您的驱动程序。这就是“keep ours”与“git merge-file --ours”不同的地方。前者更像-s ours 策略:它完全忽略了基础文件和其他/他们的文件。后者采用的是“两者都改变​​,但如果发生冲突,偏爱我们”的决议方法,和-X oursextended-strategy-option类似。

【讨论】:

  • 非常感谢您的精彩回复。
【解决方案2】:

在 6 之后,master 和 release 都提升了他们的版本。您没有确切提到颠簸版本需要什么,但我假设同一文件中的相同行已被编辑到两个分支中,这将导致冲突。至于为什么 a.java 和 b.java 突然冲突,我的猜测是他们(或他们的路径)在 6 期间被编辑。

【讨论】:

  • 检查“编辑”。版本碰撞在 pom.xml 中,不属于冲突列表。 A.java 和 B.java 的实际内容有冲突。这就是奇怪的部分,除了 2 和 4,没有任何东西触及 A 和 B。
  • 在 5 和 7 之间发布时是否有额外的提交?
  • 是的,但他们都没有触及 A 或 B 或任何 poms
  • 我几乎没有想法了:-P。你确定5成功了吗?由于您手动进行提交,因此可能发生了一些奇怪的事情。
  • 告诉我吧!!据我检查主分支和发布分支的历史记录,甚至在分离模式下检查单个中间提交,5 或 6 似乎没有任何问题。
猜你喜欢
  • 1970-01-01
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-18
  • 2017-02-26
  • 1970-01-01
  • 2020-08-23
相关资源
最近更新 更多