目标是,如果文件发生冲突,则
1) 让 git 将文件标记为“冲突”,并且
2) 能够在文件的未合并版本(“我们的”版本和“他们的”版本)之间使用 Beyond Compare。
我会警告说,虽然这在简单的情况下会很好地工作,但它确实会在某种程度上击败通常使用的 3 路合并方法(即,您没有查看合并基础上下文中的更改),所以在一些更复杂的情况下,这不会那么容易。 (出于这个原因,我建议您熟悉一种更“标准”的冲突解决方法,以便您至少可以在必要时使用它。)
但肯定有几种方法可以做到这一点。最简单的就是正常启动合并
git checkout our_branch
git merge their_branch
然后,当它发生冲突时,将工作树恢复为“我们的”版本
git checkout --ours path/to/conflicted/file
如果您已将 Beyond Compare 配置为用作差异工具,那么您可以跳过结帐并直接
git diff our_branch their_branch -- path/to/conflicted/file
但这里的缺点是 BC 不会打开您的文件的工作版本,因此您可能没有直接编辑它所需的支持。
因此,另一种设置更复杂但使用更自动化的选项是设置自定义合并驱动程序。每当给定文件的“我们的”版本和“他们的”版本都发生更改(相对于“基本”版本)时,自定义合并驱动程序就会启动。它是一个脚本,它接收代表文件各种版本的临时文件的名称作为参数。它在“我们的”版本的路径上创建(暂定)合并结果,并返回指示是否发生冲突的状态。
合并驱动程序在merge 属性(https://git-scm.com/docs/gitattributes)的文档中进行了描述。这也表明,给定一个已配置的合并驱动程序,您可以将它与给定路径上的文件关联到一个.gitattributes 文件。 (您可以将它与您的 repo 中的所有路径与 * 的条目相关联,但是如果您的 repo 可能包含二进制文件,您可能希望避免这样做,或者注意您的驱动程序脚本对二进制文件也有合理的行为.)
脚本本身会尝试正常的合并
git merge-file -p <ours> <base> <theirs> > <temp-path>
(其中<ours>、<base> 和<theirs> 来自脚本的参数,<temp-path> 是一个新的临时文件)。如果此命令返回 0(无冲突),脚本会将输出 (<temp-path>) 移动到“我们的”版本并返回 0。否则它将删除临时文件,保持“我们的”不变,并返回非零价值。
现在,这将使您的合并工作与第一种方法非常相似,除了您可以跳过git checkout --ours。那可能不值得。但此解决方案的优势在于,您可以在此基础上做更多事情。
上述所有解决方案的问题是,如果文件包含任何冲突,则该文件的所有更改(包括非冲突更改)都不会自动合并。您必须手动处理整个文件(使用 Beyond Compare 或其他)。
您可以优化合并驱动程序脚本,以便在发生冲突时使用--ours 策略选项重新运行合并
git merge-file --ours <ours> <base> <theirs>
(您仍然希望先在没有--ours 选项的情况下运行,以便知道是否发生任何冲突。如果存在 冲突,则删除临时文件,使用@ 重新运行987654338@ 选项 - 但没有 -p 或输出重定向 - 并且再次返回非零值,以便 git 知道存在冲突。)
最后,请注意,如果您只运行与 -s ours(完全忽略其他分支内容)或 -X ours(解决支持“我们的”版本并且报告没有冲突)。