在没有冲突的情况下自动合并 git(使用逐字差异而不是逐行)

Ada*_*uša 5 git git-diff git-merge git-merge-conflict

我想自动合并提交,其中每个提交更改同一行上的不同单词。目标是使用git作为文档存储并以编程方式访问它(因此,理想情况下无需解决冲突)。在我的用例中,我确信更改不会重叠(它们不会影响相同的单词,尽管位于同一)。

git-diff可以向我展示两次提交之间的差异,不仅是每行,而且是每个单词或每个字符。例如:

$ git diff --word-diff-regex=. HEAD HEAD~
Run Code Online (Sandbox Code Playgroud)

如果git-diff可以识别发生变化的单词(而不是整行),我确信我可以git-merge逐字(或逐字符)地检测冲突。我错了。根据我的理解(来源),在深处,该git-diff工具在行上运行,并且单词或字符差异功能已经与 git 返回的这些基于行的结果一起使用。

在这个答案中,建议使用干净污迹过滤器,以便将每个单词存储在快照中的单独行上。然而,在我看来,这太过分了。

你会选择什么方法?

tor*_*rek 4

为了让 Git 按照您希望的方式工作,您需要做的是修改合并代码。理论上这并不太难。实际上,我不确定它会有多困难。

\n\n

另一个答案中,我提到了 xdelta。更准确地说,Git 使用xdeltalibxdiff的修改版本。 Git 源代码将大部分代码放在子目录中。 在上一层,您会发现更多与该库一起使用的代码,例如xdiff-interface.c

\n\n

如果您修改这些以允许 xdiff 代码将“单词”(可能由任何空格分隔)而不是“行”视为 Myers、耐心和直方图算法的单独符号,并类似地修改调用代码,您应该能够让 Git 根据单词而不是行进行合并。(Git 现在添加了一个“锚点”,您可能需要对此做一些事情;我还没有研究它是如何工作的。)您还必须选择如何插入任何冲突标记\xe2\x80\x94,大概是这样,围绕这些以空格分隔的单词。

\n\n

算法本身涉及两个不同输入中的符号匹配(或无法匹配) 。不幸的是,在 libxdiff 中,符号始终是行。标准(非 Git 修改的)libxdiff 接口记录在此处,并且接口本身以整个文件为中心,libxdiff 代码进行自己的换行。

\n\n

在修改后的 xdiff 内部,Git 看起来好像将每一行分配给一个“记录”,以便它所比较的​​符号是逐条记录进行比较的。如果您将每个以空格分隔的单词分配给一条记录,那么您基本上会得到您想要的结果,而忽略(稍后)处理分隔实际记录的任何实际空格的小问题。也就是说,在 中xdl_hash_record,您要做的就是停在任何空白处而不是换行符处,然后在查找“下一条”记录时丢弃该行与下一行之间的额外空白,以自行构建记录。调用此更改的差异的代码可能必须更改,因为它可能假设“记录号”意味着“行号”(这对我来说并不清楚)。

\n\n

(如果您在每个记录中包含前导或尾随空格,并且只有比较函数xdl_recmatch\xe2\x80\x94 在同一文件中 \xe2\x80\x94 则可能会工作得更好,如果符号匹配(排除空格),则表示符号匹配. 请注意,xdl_hash_record还应该对减去空白的符号进行哈希处理:如果符号匹配,差异引擎要求哈希值匹配,并且为了性能,如果符号不同,则希望哈希值不同。测试本质上是这样的:符号如果 H1 == H2 和 recmatch(S1,S2) 表示它们匹配,则具有哈希值 H1 和 H2 的 S1 和 S2 匹配。当符号明显不同时,H1==H2 测试消除了许多减慢“比较”速度的子例程调用,但对于哈希值匹配的符号,需要调用来验证它们是否确实相同。)

\n\n

主要的 Myers 算法本身的时间复杂度为 O(ND),其中 N 是符号数量,D 是差异数量\xe2\x80\x94,即最终编辑脚本\xe2\x80\x94 之间的长度两个输入集。当符号为行时,1000行文件有1000个符号;当符号是单词时,1000行文件可能有30000个符号。所以这显然会慢一些,但至少通常是线性慢的。直方图和耐心算法是 Myers 的修改,我认为它们在时间上的表现应该类似,但我还没有真正正确地研究过它们。)

\n