我想自动合并提交,其中每个提交在同一行上更改一个不同的单词。目标是使用 git 作为文档存储并以编程方式访问它(因此,理想情况下不必解决冲突)。在我的用例中,我确定这些更改不会重叠(尽管它们位于相同的 line 上,它们不会影响相同的 words )。>
git-diff
不仅可以显示每行,而且还可以显示每个单词或每个字符两次提交之间的差异。例如:
$ git diff --word-diff-regex=. HEAD HEAD~
如果git-diff
可以识别出已更改的词(而不是整行),那么我确信我可以使git-merge
逐词(或逐字符)检测冲突)基础。我错了。从我的理解(source)来看,git-diff
工具在行上运行,单词或字符差异功能已经可以与git返回的这些基于行的结果一起使用。
在此answer中,建议使用 clean 和 smudge 过滤器,以便将每个单词存储在快照中的单独一行上。但是,在我看来,这太过分了。
您会选择哪种方法?
答案 0 :(得分:1)
要使Git以您希望的方式工作,您需要做的就是修改合并代码。从理论上讲,这不太困难。实际上,我不确定结果会是多么困难。
在that other answer中,我提到了xdelta。更准确地说,Git使用xdelta和libxdiff的修改版本。 The Git source puts most of this code in a subdirectory.上一层,您会发现更多与该库一起工作的代码,例如xdiff-interface.c。
如果修改了这些内容以允许xdiff代码将“单词”(大概用任何空格分隔)而不是“线”作为Myers,耐心和直方图算法的单独符号,则修改了调用代码同样,您应该能够让Git根据单词而不是行进行合并。 (Git现在添加了您可能需要做的“锚定”操作;我没有研究它的工作原理。)您还必须选择如何插入任何冲突标记,大概是在这些空白周围-分隔的单词。
算法本身涉及两个不同输入中的匹配(或不匹配)符号。不幸的是,在libxdiff中,符号始终是行。 here记录了标准的(未经Git修改的)libxdiff接口,该接口本身位于整个文件的中心,并且libxdiff代码进行了自己的换行。
在修改后的xdiff内部,Git似乎将每行分配给一个“记录”,以便它比较的符号逐条记录。如果您将每个用空格分隔的 word 分配给一条记录,您将大体上得到所需的内容,而忽略了(以后)处理将实际记录分隔开的任何实际空白的小问题。也就是说,在xdl_hash_record
中,您要做的就是停在 any 空格而不是换行符,然后在找到“ next”时丢弃此行与下一行之间的其他空格。记录,以自己建立记录。更改此差异的代码调用可能必须更改,因为它可能假定“记录号”暗含“行号”(这对我来说不是很清楚)。
(如果您在每条记录中包含前导或尾随空白,并且在同一文件中仅具有比较功能xdl_recmatch
,则可能会更好,例如,如果符号匹配但排除了空白,则表示它们匹配请注意xdl_hash_record
也应该对符号进行散列运算符减去空格:如果符号匹配,diff引擎要求哈希值匹配,并且为了提高性能,如果符号不同,哈希值也要有所不同。 ,是这样的:如果H1 == H2并且recmatch(S1,S2)表示匹配,则具有散列H1和H2的符号S1和S2匹配。H1 == H2测试消除了很多子程序调用当符号明显不同时减慢“比较”的速度,但是对于哈希匹配的符号,要求调用以确认它们确实相同。)
Myers主算法本身具有时间复杂度O(ND),其中N是符号数,而D是两个输入集之间的差值(即最终编辑脚本的长度)。当符号为线时,1000行文件中有1000个符号;当符号是单词时,1000行文件可能包含30000个符号。因此,这显然会更慢,但至少通常线性更慢。直方图和耐心算法是Myers的修改,我认为应该在时间上表现类似,但是我还没有真正研究它们。)