在mercurial(或git)中以编程方式预合并

在mercurial(或git)中以编程方式预合并,git,merge,mercurial,Git,Merge,Mercurial,我们经常会遇到某些常见的、非信息性的合并冲突,尤其是在合并回归测试输出时。我希望能够以编程方式忽略与某些模式匹配的行(例如,“如果某行或区域与此regexp匹配,只需从其他行获取修补程序”),但我仍然希望使用交互式合并工具来处理文件中的其他冲突(如果有冲突,则无需手动重新合并这些第一行) 如果我与任何工具(如:merge3或我可能设计的任何工具)预合并,然后与另一个工具重新合并,它似乎总是从头开始。对于我已经解决的冲突,有没有办法“保存我的工作”呢 我们使用的是mercurial,但是如果在gi

我们经常会遇到某些常见的、非信息性的合并冲突,尤其是在合并回归测试输出时。我希望能够以编程方式忽略与某些模式匹配的行(例如,“如果某行或区域与此regexp匹配,只需从其他行获取修补程序”),但我仍然希望使用交互式合并工具来处理文件中的其他冲突(如果有冲突,则无需手动重新合并这些第一行)

如果我与任何工具(如
:merge3
或我可能设计的任何工具)预合并,然后与另一个工具重新合并,它似乎总是从头开始。对于我已经解决的冲突,有没有办法“保存我的工作”呢

我们使用的是
mercurial
,但是如果在
git
中的过程类似,请告诉我。

在git中的过程不同,但是您应该能够在任何一个系统中实现您想要的

TL;DR是指您必须编写自己的合并工具(或Git中的合并驱动程序)。这个合并工具应该比较这三个输入文件,并执行您想要的任何合并操作,然后使用一组新的基本文件和输入文件运行普通的低级合并驱动程序

长的 首先,请注意Mercurial对“premerge”有自己的定义。有关更完整的说明,请参阅。我把你的问题解释为根本不涉及这种预合并;相反,您希望编写Mercurial所指的合并工具。(Git称之为合并驱动程序。)

让我们来讨论一些定义,以便大家在术语上达成一致。当运行
hgmerge
gitmerge
时,选择两个特定的提交进行合并。一个是您当前的提交,我们将其称为本地,因为Mercurial使用该名称。出于同样的原因,我们会打电话给对方。(Mercurial有时会将第二个调用为remote,但大部分仅在内部调用。Git会可变地调用这些
--我们的
--他们的
,或者本地和远程,或者本地和其他:Git根本不擅长保持一致性。)

您签出本地提交并运行
hgmergeother
gitmergeother
,Mercurial或git将找到合并基提交,它们都称之为合并基提交或仅称之为基提交

在这两个系统中,所有三个有趣的提交都表示为快照:以下是基本提交的文件。以下是与本地提交相同的(可能是一些新的、删除的、重命名的)文件。以下是与其他提交相同的文件。嘿,手鼓先生,给我合并一下

高级合并 VCS必须做的第一件事是将每个基本提交文件与每个本地提交文件和每个其他提交文件配对。一个文件作为一个整体可能有两个这样的操作(创建、重命名或删除)。特别是,如果在一次或两次提交中重命名了文件,则VCS必须处理此问题。如果文件在一次或两次提交中被删除,VCS必须处理该问题。如果在两次提交中都创建了一个不存在于基中的文件,则VCS也必须处理该文件。其中一些很简单:如果文件F只是在两次提交中的一次中重命名,那么,我们只需在最终结果中重命名它,而不是像往常一样合并更改。但其他更改会相互冲突:如果双方都提交文件,VCS应该使用哪个名称?我把这些冲突称为高级冲突

在这方面,Git比Mercurial有一些优势。Mercurial让您立即为每个高级冲突选择解决方案,以便它知道每个文件的最终命运。2 Git让您推迟这个决定(尽管Git中的底层实现存在问题)。稍后我会再多提一点。这一部分,您无法在Mercurial中很好地实现自动化(或者至少在我上次尝试时无法做到)。幸运的是,对于两家风险投资企业来说,这种冲突往往很少发生

低级合并 现在我们知道了所有文件的命运(或者推迟了Git中的决定),Mercurial将特别使用您选择的工具(通过
--tool
$HGMERGE
)合并每个文件。我将其称为低级合并,以区别于将文件配对并确定其名称的高级过程。有关此低级合并过程的概述,请参见

请记住,我们有三个输入:base、local和other。最终合并将有两个父级:本地和其他。我们可以将每个低级文件与基础文件相比,认为它们在父级或父级中被“更改”。或者,该文件可能与双亲中的一个或两个相同。如果文件根本没有被碰过,如果它在所有三次提交中都完全相同,则无需做任何事情:最终文件应与基础文件匹配。如果该文件在本地或其他版本中仅在一个父级中被修改过,那么就基本内容而言,仍然没有什么可做的,真的;我们可以用修改过的

如果文件在两个父级中都以完全相同的方式进行了更改,那么使用哪一个父级无关紧要。但请注意,该过程适用于:

对于双亲中更改的每个文件

这里有一些微妙之处,值得一看Git和Mercurial之间的另一个区别

在Git中,当我们有来自B(base)、L(local)和O(other)的三个文件时,我们真正拥有的是三个散列ID。散列ID唯一标识内容,因此我们可以立即判断哪些文件匹配,哪些不匹配。如果L=O,则两个父项都有相同版本的文件,我们只取其中一个,而不考虑B(要么都做了相同的更改,要么没有人做任何更改)。否则,如果B=L或B=O,我们取它不匹配的那一个,因为那是有变化的父项。否则(B)≠ 五十、 B≠ O、 L≠ O) 我们必须进行真正的合并

Mercurial不按h存储文件
mymergetool.args = $local $other $base -o $output
driver = filfre %O %A %B