【发布时间】:2018-01-06 05:59:52
【问题描述】:
从git merge documentation 中提取的递归合并策略的定义。
这只能使用 3 路合并算法解决两个头。当有多个共同祖先可用于 3 路合并时,它会创建共同祖先的合并树并将其用作 3 路合并的参考树。据报道,通过对取自 Linux 2.6 内核开发历史的实际合并提交进行的测试,这会导致更少的合并冲突,而不会导致错误合并。此外,这可以检测和处理涉及重命名的合并。这是拉取或合并一个分支时的默认合并策略。
递归策略可以采用以下选项:
如上所述,作为默认策略的递归策略使用 3 路递归合并算法(解释为 here 和 Wikipedia)。
我的理解是,必须手动解决冲突的大块,它们通常是这样表示的
<<<<<<<<<<<
developer 1's code here
============
developer 2's code here
>>>>>>>>>>>
递归合并策略的ours选项记录如下:
此选项通过支持 我们的 版本来强制自动解决冲突的块。与我们这边不冲突的另一棵树的更改会反映到合并结果中。对于二进制文件,全部内容都取自我们这边。
这不应与 ours 合并策略混淆,后者甚至根本不查看其他树包含的内容。它丢弃了其他树所做的一切,并声明我们的历史记录包含其中发生的一切。
现在假设我有两个分支 Y 和 M 的头,它们有一个共同的基础祖先 B,如下所示
当使用默认递归策略合并 Y 和 M 时,第 30 行将变为Print("hello");,因为在第 30 行,Y 表示从基本祖先的变化,而 M 没有。但是如果我在分支 M 上运行
git merge -s recursive -X ours Y
第 30 行会在合并输出中变为 Print("bye"); 吗?
对于那些说这很明显的人,请注意我们的选项声明
此选项强制冲突的帅哥通过支持我们的版本来干净利落地自动解决。
但是(据我所知)第 30 行没有冲突的大块。
为了完整起见,我还将提供他们的选项的文档:
这与我们的相反。
我们的策略的文档如下:
这解决了任意数量的头,但合并的结果树始终是当前分支头的树,有效地忽略了所有其他分支的所有更改。它旨在用于取代分支的旧开发历史。请注意,这与 recursive 合并策略的 -Xours 选项不同。
所以回到上面的例子,如果我跑了
git merge -s ours Y
在分支 M 上,很明显第 30 行将是合并输出中的Print("bye");。在这种情况下,为什么也没有他们的策略?我怎样才能实现与我们的策略相同和相反的行为?
我问这个问题是因为我正在处理一个项目,只要开发分支上的代码成功构建,我想定期完全用另一个开发分支的更改覆盖主分支。这样我可以确保我的开发分支永远不会偏离主分支太远,并且主分支上的代码将成功构建。
我见过this question推荐的解决方案
git checkout dev-branch
git merge -s ours master
但 Git 只是输出 Already up-to-date,尽管这两个分支包含不同的代码(而 dev-branch 实际上是 master 之前的几个提交)。
我目前的解决方案是这样做
git merge -s recursive -X theirs dev-branch
我还看到了this question,它建议使用 recursive 策略的 theirs 选项。但是,由于 recursive 策略的 ours 选项显然不同于 ours 策略,因此 theirs 选项也是如此递归策略与我所说的他们的策略不同。
【问题讨论】:
-
这个问题重复了很多其他问题的很多部分。考虑一下我对stackoverflow.com/q/42099431/1256452stackoverflow.com/q/44212642/1256452 和stackoverflow.com/q/44858155/1256452 的回答(也许从最后一个开始?)。
标签: git github version-control merge