考虑以下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
A.java
分支feature-foo
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 clone
5
和7
是在具有完整/path/to/tmp
git clone
上手动完成的
feature-foo
被合并回主人(接受MR)master
的1
已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
(它试图将其带到主人身上)和B.java
(它试图将过时的发布分支合并到主分支中并产生冲突)。
我的问题是:
修改
pom.xml
内的版本已被添加到.gitattributes
,以便使用我们的策略进行处理。
答案 0 :(得分: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。)
如果有多个合并库,则会遇到一些问题。使用-s recursive
合并策略的Git默认是合并基础。此合并的结果是一个新的“虚拟提交”,然后将其视为最终合并的合并基础。当你可以(递归地)执行我将要手动描述的内容时,它会非常痛苦:除了其他事项,您可能必须为每个潜在的虚拟提交进行实际提交。但幸运的是, 1 只有一个合并基础,也许毕竟提交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
此处 tip-1 为master
, tip-2 为release-1.0.x
。合并基础提交当然是您在上面找到的(单个)哈希ID。
如果所有三个提交中都存在两个有问题的文件,那么你不会遇到任何重命名问题,所以我甚至不会把它们带到这里。
1 嗯,从技术上讲,这不是运气问题。只有在进行十字交叉合并时才会出现合并基础模糊,即使这样,它们也需要具有相同的“距离”。因此,生成多个合并基础相对困难。
最后,还有最后一点。它最终可能很重要,但实际上这不是问题。它认为:
pom.xml
内的版本已被添加到.gitattributes
,以便使用我们的策略进行处理。
无法在.gitattributes
中获得真正的“我们的”策略。 (甚至没有“我们的”标记。)我在这里猜你的意思是你写了一个合并驱动程序,当有一个<{1>} 时,它实际上使用了git checkout --ours
冲突。您也可能编写了一个在三个输入上使用git merge-file --ours
的合并驱动程序。
这些都略有不同。
首先要知道的是,如果Git发现冲突,您的合并驱动程序仅运行。
当您执行上述两个git diff -M
命令时,您可以看到哪些文件包含需要组合的更改。如果,与合并基础 B 相比,两个分支提示都有一个不同的 pom.xml
,那么就有一些东西需要合并。也就是说,假设在diff#1中我们看到:
-this
+that
在差异#2中我们看到:
-another
+another
这些需要组合,因此Git将调用您的合并驱动程序。 (更准确地说,Git会检查三个哈希ID:基本文件的哈希值,提示#1中的文件哈希值以及提示#2中的文件哈希值。如果所有三个不同,Git将调用您的合并驱动程序。 )
另一方面,也许只有#1提示或只有#2提示更改文件(因此它在底座中与在另一个提示中相同)。在这种情况下,Git会选择一个更改过的文件,而不运行驱动程序。对于像pom.xml
这样的文件,这通常可能就是你想要的! (对于版本编号,它可能不是你想要的,但也许你有另一个步骤来处理它。)
如果Git 调用你的驱动程序,那么它当然取决于你的驱动程序。这就是“保持我们的”与“git merge-file --ours”不同的地方。前者更像是-s ours
策略:它完全忽略了base和other / theirs文件。后者使用“同时进行两项更改,但如果发生冲突,请使用我们的解决方案方法,并且类似于-X ours
扩展策略选项。
答案 1 :(得分:0)
6岁之后,主人和发行版都碰到了他们的版本。你没有确切地提到碰撞版本的含义,但是我假设同一文件中的相同行被编辑到两个分支中,这将导致冲突。至于为什么a.java和b.java突然发生冲突,我的猜测是他们(或他们的路径)是在6日编辑的。