自动合并 git 无冲突(使用逐字差异而不是逐行差异)

Automatic merging in git without conflicts (using word-by-word diff instead of line-by-line)

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

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

$ git diff --word-diff-regex=. HEAD HEAD~

如果 git-diff 可以识别更改的单词(而不是整行),我确信我可以 git-merge 检测逐字(或逐字符)的冲突-字符)基础。我错了。根据我的理解 (),深入来说,git-diff 工具对行进行操作,并且单词或字符差异功能已经适用于 git 返回的这些基于行的结果。

在这个 answer 中,建议使用 cleansmudge 过滤器来存储每个快照中单独一行的单词。但是,在我看来,这似乎太老套了。

您会选择哪种方法?

要使 Git 以您希望的方式工作,您需要做的是修改合并代码。理论上这并不太难。在实践中,我不确定它会变得多么困难。

, I mention xdelta. More precisely, Git uses modified versions of both xdelta and libxdiff. The Git source puts most of this code in a subdirectory. Up one level you'll find a few more bits of code that work with the library, such as xdiff-interface.c.

如果您修改这些以允许 xdiff 代码将 "words"(可能由任何白色 space 分隔)而不是 "lines" 作为 Myers 的单独符号,请耐心等待和直方图算法,并类似地修改了调用代码,您应该能够获得 Git 以基于单词而不是行进行合并。 (Git 现在添加了一个 "anchor" 东西,你可能需要做一些事情;我还没有研究它是如何工作的。)你还必须选择如何插入任何冲突标记——大概, 围绕这些白色-space-分隔的单词。

算法本身关注匹配(或不匹配)两个不同输入中的符号。不幸的是,在 libxdiff 中,符号总是线。标准(未 Git 修改)libxdiff 接口已记录 here,接口本身以整个文件为中心,libxdiff 代码自行换行。

在修改后的 xdiff 内部,看起来好像 Git 将每一行分配给 "record",以便它比较的符号是逐个记录的。如果您将每个白色 space 分隔的 单词 分配给一条记录,那么您基本上会得到您想要的,忽略(稍后)处理任何实际的小问题white-space 分隔实际记录。也就是说,在 xdl_hash_record 中,您要做的就是停在 any white-space 而不是换行符处,然后丢弃额外的 white space这一行和下一行在找到 "next" 记录时,自己构建记录。代码 调用 这个改变的 diff 可能必须改变,因为它可能假设 "record number" 暗示 "line number" (这对我来说不是很清楚)。

(如果在每条记录中包含前导或尾随白色 space,并且只具有比较功能,xdl_recmatch——在同一个文件中——假设符号匹配如果他们匹配排除他们的 whitespace。请注意 xdl_hash_record 应该散列符号减去 whitespace 以及:diff 引擎要求散列匹配如果符号匹配,并且为了性能,如果符号不同,则希望散列不同。测试本质上是这样的:符号 S1 和 S2 与散列 H1 和 H2 匹配,如果 H1 == H2 并且重新匹配(S1,S2)表示它们match. H1==H2 测试在符号明显不同时消除了很多对慢 "compare"s 的子程序调用,但是对于哈希匹配的符号,需要调用来验证它们是真的一样。)

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