使用逐字逐句的差异比逐行差异进行git自动合并(无冲突)。

7
我想自动合并那些每一次提交都改变同一行不同单词的提交记录。目的是将git用作文档存储,并以编程方式访问它(因此,理想情况下无需解决冲突)。在我的用例中,我可以确定更改不会重叠(它们不会影响相同的单词,尽管它们在相同的上)。 git-diff不仅可以按行显示两个提交之间的差异,还可以按单词或字符显示差异。例如:
$ git diff --word-diff-regex=. HEAD HEAD~

如果git-diff能够识别更改的单词(而不是整行),我相信我可以让git-merge基于单词(或字符)检测冲突。但我错了。据我所知(来源),在深层次上,git-diff工具操作的是行,单词或字符差异功能已经使用这些由git返回的基于行的结果进行操作。
在这个答案中,建议使用“clean”和“smudge”过滤器,以便将每个单词存储在快照的单独行中。然而,那对我来说似乎太过hacky。
您会选择哪种方法?
1个回答

4
你需要做的是修改合并代码,使Git按照你的意愿工作。理论上来说,这并不太难。但实际上,我不确定会有多困难。
另一个答案中,我提到了xdelta。更准确地说,Git使用了经过修改的xdeltalibxdiff的版本。Git源代码将大部分此类代码放在子目录中。在上一级目录中,你会找到更多与该库一起工作的代码片段,例如xdiff-interface.c
如果您修改了这些内容,让xdiff代码将“单词”(被任何空格分隔的)而不是“行”作为Myers、patience和histogram算法的独立符号处理,并相应地修改调用代码,那么您就可以让Git基于单词而不是行进行合并。(Git现在添加了一个“锚点”东西,您可能需要对此进行一些操作;我还没有看过它是如何工作的。)您还需要选择如何插入任何冲突标记-大概是在这些由空格分隔的单词周围。
这些算法本身关注匹配(或未能匹配)两个不同输入中的符号。不幸的是,在libxdiff中,这些符号总是行。标准(非Git修改的)libxdiff接口在这里有文档记录,接口本身以整个文件为中心,libxdiff代码会进行自己的换行。
在修改后的xdiff内部,Git似乎会将每行分配给一个“记录”,以便比较的符号是逐个记录比较的。如果你将每个由空格分隔的单词分配给一个记录,那么你大多数情况下都能得到你想要的结果,忽略实际记录之间的任何实际空格。也就是说,在xdl_hash_record中,你所要做的是在任何空格处停止,而不是在换行符处停止,然后在查找“下一个”记录时丢弃此行和下一行之间的额外空格,以构建记录本身。调用这个改变过的diff的代码可能必须更改,因为它可能假设“记录号”意味着“行号”(这对我来说不是很清楚)。
(如果您在每个记录中包含前导或尾随空格,并且仅将比较函数 - 在同一文件中 - 表示符号匹配,如果不包括它们的空格,则可能会更好。请注意, 也应该哈希减去空格的符号:差异引擎要求哈希匹配如果符号匹配,并且出于性能考虑,希望哈希在符号不同的情况下不同。本质上,测试是这样的:如果H1 == H2并且recmatch(S1,S2)表示它们匹配,则符号S1和S2的哈希值为H1和H2。H1==H2测试消除了许多子例程调用,使符号显然不同时缓慢的“比较”,但对于哈希匹配的符号,需要调用来验证它们是否真的相同。)
主要的Myers算法本身的时间复杂度为O(ND),其中N是符号数量,D是两个输入集之间的差异数量,即最终编辑脚本的长度。当符号为行时,1000行文件有1000个符号;当符号为单词时,1000行文件可能有30000个符号。因此,这会慢一些,但至少通常是线性的慢。直方图和耐心算法是Myers的修改版,应该在时间上表现类似,但我还没有真正研究过它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接