如何在统一的diff文件中可视化每个字符的差异?


122

说我得到一个用创建的补丁git format-patch。该文件基本上是带有某些元数据的统一差异。如果在Vim中打开文件,则可以看到哪些行已被修改,但是看不到更改后的行中的哪些字符不同。有谁知道一种方法(在Vim或在Ubuntu上运行的其他一些免费软件中)可视化每个字符的差异?

执行时显示每个字符diff的反例vimdiff a b

更新2010年11月12日星期五12:36:23 UTC

diffpatch对于使用单个文件的情况很有帮助

更新2016年6月16日星期四17:56:10

在git 2.9中检查diff-highlight。该脚本完全符合我最初的要求。


在superuser.com上可能会更好
Daenyth

12
也许。我选择了stackoverflow.com,因为FAQ提到了这里是“程序员常用的软件工具”问题的
发源地

7
我不确定这是否可以直接回答您的问题,但是git diff --color-words对于仅查看行中哪些单词已发生变化,而不是通常的统一diff输出非常有用。不过,它是基于单词而不是基于字符的,因此,如果要扩散的内容中没有太多空格,则输出可能会不太整洁。(编辑:糟糕,我发现我误会了您的要求-尽管如此,此评论可能对某人有用。)
马克·隆air

Answers:


13

给定您在问题中对Vim的引用,我不确定这是否是您想要的答案:)但是Emacs可以做到这一点。打开包含DIFF文件,确保您在是diff-mode(如果该文件名为foo.difffoo.patch自动发生这种情况,否则型M-x diff-mode RET),请你有兴趣,并击中了大块C-c C-brefine-hunk。或通过一次粗暴地浏览文件M-n; 这将自动进行精炼。


1
为我工作!嘿,我已经使用Vim 10年了,但是我刚刚安装了emacs。:)
亚当·蒙森

但是emacs不支持从stdin读取信息,例如,我不能这样做git log master.. -p | emacs -
Hi-Angel

1
@ Hi-Angel您可以打开Emacs并键入M-!运行命令,然后将输出捕获到缓冲区中。
legoscia

172

在git中,您可以合并而无需提交。首先合并您的补丁,然后执行:

git diff --word-diff-regex=.

注意等号后的点。


139
更好:git diff --color-words=.
ntc2 2013年

4
@ ntc2您应该将您的评论作为答案。
Tyler Collier 2014年

1
支持者请注意,我的原始用例假定您只有补丁文件,没有git repo甚至没有基础版本/修改版本。这就是为什么我接受@legoscia的答案...它准确描述了要求的原因。
亚当·蒙森

2
@ ntc2 git diff --color-words=.git diff --color-words .工作方式有所不同。更好的是git diff --color-words .
Abhisekp,2015年

2
@abhisekp:谢谢你的照片。我想我想通了:git diff --color-words .的确与git diff --color-words -- .!即,将.解释为路径。您可以通过进行验证mkdir x y; echo foo > x/test; git add x/test; git commit -m test; echo boo > x/test; cd y; git diff --color-words=.; git diff --color-words .; git diff --color-words -- .
ntc2

145

这是一些输出噪音小于的版本,git diff --word-diff-regex=<re>并且输入的次数少于,但等同于git diff --color-words --word-diff-regex=<re>

简单(突出显示空间变化):

git diff --color-words

简单(突出显示各个字符更改;不突出显示空格更改):

git diff --color-words=.

更复杂(突出显示空间变化):

git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'

一般来说:

git diff --color-words=<re>

其中<re>是定义“字”用于识别改变的目的,正则表达式。

这些噪声较小,因为它们为更改的“单词” --word-diff-regex=<re>着色,而仅使用带有彩色-/+标记的环绕匹配的“单词” 。


9
我自己喜欢--color-words,没有=.一部分。
Tyler Collier 2014年

1
git diff --color-words='\w'会更好地与变音符号一起使用(git v1.7.10.4)
NR

1
您更复杂的版本效果很好。我附加了--word-diff=plain,另外具有[--]周围的删除{+以及+}周围的添加。但是,正如手册中所警告的那样,这些定界符在源中的实际出现不会以任何方式逃脱
Tobias Kienzler 2015年

2
不幸的是,您更复杂的版本似乎未突出显示例如缩进更改,我对此提出一个问题
Tobias Kienzler 2015年

这个答案很棒!但是,是否有办法将这些更改的背景实际更改为绿色/红色?
WoLfPwNeR '16

45
git diff --color-words="[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+"

上面的正则表达式(来自Thomas Rast)在标点/字符级别(虽然不像一样嘈杂)上很好地分离了diff片段--word-diff-regex=.

我在此处发布了结果输出的屏幕截图。


更新:

本文有一些不错的建议。具体来说,contrib/git repo 的树具有一个diff-highlightperl脚本,该脚本显示了细粒度的突出显示。

快速开始使用它:

$ curl https://git.kernel.org/cgit/git/git.git/plain/contrib/diff-highlight/diff-highlight > diff-highlight
$ chmod u+x diff-highlight
$ git diff --color=always HEAD~10 | diff-highlight | less -R

5
您可以将其缩短为--color-words=[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
Eddified

我必须将'值的开头添加到那里。否则我得到一个错误。另外,我只是简单地使用--color-words与正则表达式完全相同的行为。
gcb

3
@gcb文本内容很重要。如果您的更改由空格分隔,则没有任何区别。但是,如果您进行更改(如果您更改了类似的内容)foo.barfoo.qux您将看到差异。
贾斯汀·凯斯

5
更简单:git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'
ntc2 2013年

1
我已经在Homebrew上安装了git,并且已经在有了该脚本/usr/local/share/git-core/contrib/diff-highlight/diff-highlight似乎表明Homebrew的git确实在中安装了整个contrib /usr/local/share/git-core/contrib/。所以最后,下面的工作对我来说git diff --color=always | /usr/local/share/git-core/contrib/diff-highlight/diff-highlight
Ashutosh说金达尔

6

如果您不反对安装NodeJS,则有一个名为“ diff-so-fancy”的软件包(https://github.com/so-fancy/diff-so-fancy),该软件包非常易于安装且运行良好:

npm install -g diff-so-fancy
git diff --color | diff-so-fancy | less -R

编辑:刚刚发现它实际上是官方diff-highlight的包装...至少像我这样的憎水者安装起来更容易,并且GitHub页面有很好的文档记录:)


2

我不知道每个字符的差异工具,但是有一个每个单词的差异工具:wdiff。

请参阅示例UNIX / Linux上的前4个文件差异工具-Diff,Colordiff,Wdiff,Vimdiff


wdiff很有趣,谢谢!为了澄清我的原始问题,我正在寻找可以为单个文件提供统一语法格式的增强型语法突出显示功能。
亚当·蒙森

稍微偏离主题(关于逐字差异,不增强现有的差异输出),但是我发现以下组合最适合逐字可视化:* wdiff old_file new_file | cdiff * vimdiff ,然后在vim :windo wincmd K内以便切换到垂直窗口布局(一个在另一个下方)从一个并排。对于长行文件,这种布局要好得多。
亚历山大·亚当夫斯基

2
顺便说一句,一些其它工具值得一试,而不是链接的文章中提到:wdiff2mdiff,和谷歌的在线工具
亚历山大·亚当夫斯基

1

经过一番研究后,我发现这个问题最近在Vim主邮件列表中出现了两次。该NrrwRgn插件提到两个 (使两个窄的区域差异比较及它们)。如Christian Brabandt所述,使用NrrwRgn感觉更像是一种解决方法,而不是解决方案,但这也许足够好。

我试用了NrrwRgn,它与:diffthis一起,对于说明单个文件中各个字符之间的差异确实有用。但是花了很多击键。我的Vimscript很生锈,但是可能已被编写脚本。也许可以增强NrrwRgn以提供所需的功能。

有什么想法吗?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.