如何编写一个外部Git差异比较工具,以比较添加的行和删除的行(并隐藏匹配项)?

7
在我的文本文件中,我经常移动大段内容。换句话说,我会将长度在3到50行之间的一部分剪切并无改变地粘贴到文件的其他位置。
在“未提交的更改”下,Git(我使用Github OSX)将这些行显示为在文件的某个部分中被“删除”,而在另一个部分中被“添加”。
鉴于我的工作流程,如果Git的差异显示不突出显示我仅仅是从一个地方移动到另一个地方的部分,那对我来说将会更有帮助。相反,我希望Git只突出显示全新的行和我完全从文件中删除的行。 (以及我更改了某些部分的行。)
是否有一种方法可以指示Git的差异显示忽略3行以上的“删除”部分,如果它在文件的其他地方找到相同的“添加”部分?
目前我使用 wdiff = diff-highlight
更新:看起来指定外部git diff很简单:
gitconfig
[diff]
    external = ~/prose-diffs.py 

有没有外部的git diff工具可以比较“添加”的部分和“删除”的部分(忽略开头和结尾的换行符),并自动隐藏任何添加的行与删除的行匹配的部分?


2
不是使用内置的diff,但你可以让git使用“外部diff”。这仍然存在找到(或编写)这样一个diff的问题(这就是为什么这是一条评论而不是答案的原因)。 - torek
1
我在这种情况下使用的一个技巧是在比较之前以某种方式使文本文件“规范化”。通常,我会对它们进行排序并比较排序后的文件。在某些情况下,需要删除缩进或某些标点符号。 - Roman Susi
@torek,一个程序员写这样的差异有多难?一旦编写完成,像Github Desktop OSX或Sourcetree这样的GUI客户端是否能够使用外部差异? - incandescentman
1
“有多难” 取决于你想要做好一份工作的程度:如果你添加了“移动”操作(搜索“编辑距离”),字符串到字符串的最小编辑距离问题会迅速增加复杂性,但是通过查找任何现有差异中的匹配添加/删除部分的俗套技巧将变得容易。(GUI客户端)我没有使用过它们,也不知道。 - torek
是的,后者——查找与“添加”部分匹配的“已删除”部分,并隐藏任何匹配的部分——将完全足够。 - incandescentman
2
阅读此帖以获取更多信息: https://dev59.com/cGcs5IYBdhLWcg3ww2xP - pjbrito
1个回答

2

步骤概述:

  1. 一个理解行重新排序的diff程序
  2. 使用新的diff程序-设置您的git配置

一个diff程序:

事实证明,git将使用以下参数调用您的diff程序:

> my_diff_tool <filename> <old_location> <old_hash> <old_mode> <new_location> <new_hash> <new_mode>

下面是最简单的差异比较工具,它能做到与您想要的功能接近。它读取文件,然后使用集合比较打印出新旧行。

#!/usr/bin/python
import sys

old = open(sys.argv[2]).read().splitlines()
new = open(sys.argv[5]).read().splitlines()

print "-"* 80
print "Filename: %s" % sys.argv[1]

# Simple set method
for line in set(old) - set(new):
    print '- %s' % line
for line in set(new) - set(old):
    print '+ %s' % line
if set(new) == set(old):
    print "Text reordering only"

这是一个示例,展示了它输出的内容与diff输出的内容之间的区别:
我的diff工具
Filename: test.txt
- luctus pellentesque.
+ luctus pellentesque. Puric huma te.

差异

diff --git a/test.txt b/test.txt
index 2ec8f4b..797e2ad 100644
--- a/test.txt
+++ b/test.txt
@@ -4,15 +4,15 @@ dolor quis feugiat. Nullam vel interdum leo, a placerat elit. Mauris quis
 faucibus dui.

 Nullam eu sapien quis ex convallis tincidunt. Mauris tristique mauris ac
-luctus pellentesque.
+luctus pellentesque. Puric huma te.

 Duis at imperdiet lacus. Sed malesuada elit vitae arcu semper, at fringilla
 purus rhoncus. Sed vestibulum pellentesque libero in interdum. Fusce elementum
 ornare vulputate.

+Nam sed enim at nisi tincidunt accumsan eu nec nisl. Duis suscipit hendrerit
+fermentum. Sed mattis purus congue velit aliquet, non placerat lectus varius.
+
 Donec placerat, purus ac aliquet ullamcorper, elit leo accumsan ante, sed
 lacinia leo sem sed metus.  Morbi lacinia porttitor ante, eget consequat
 libero accumsan in. Nunc sit amet lectus magna.
-
-Nam sed enim at nisi tincidunt accumsan eu nec nisl. Duis suscipit hendrerit
-fermentum. Sed mattis purus congue velit aliquet, non placerat lectus varius.

显然,还有很多需要改进的地方。例如,集合将忽略重复行。集合也会重新排序,如果有大量的新行,这会使理解更加困难。

这些改进留给读者自己练习。

使用新diff程序

将git配置设置为使用新工具很容易。您也可以像上面所示的那样修改您的.gitconfig文件。

> git config diff.external /location/to/your/diff/tool/my_diff_tool

您需要确保您的diff工具是可执行的,否则您将会得到一个错误提示(fatal: cannot exec '/location/to/your/diff/tool/my_diff_tool': Permission denied),因此:


> chmod +x /location/to/your/diff/tool/my_diff_tool

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