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

Posted

技术标签:

【中文标题】如何在统一的差异文件中可视化每个字符的差异?【英文标题】:How can I visualize per-character differences in a unified diff file? 【发布时间】:2011-03-14 23:46:19 【问题描述】:

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

执行vimdiff a b 时可视化每个字符差异的反例。

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

diffpatch is helpful 用于处理单个文件的场景。

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

查看diff-highlight in git 2.9。该脚本完全完成了我最初想要的操作。

【问题讨论】:

这在 superuser.com 上可能会更好 也许吧。我之所以选择 ***.com,是因为常见问题解答中提到这是关于“程序员常用的软件工具”问题的地方 我不确定这是否直接回答了您的问题,但git diff --color-words 对于仅查看行内单词的变化非常有用,而不是通常的统一差异输出。但是,它是基于单词而不是基于字符的,因此如果您要区分的内容中没有太多空格,那么输出可能会不那么整洁。 (编辑:哎呀,我明白我误解了你的要求 - 不过也许这个评论对某人有用。) 【参考方案1】:

经过一番研究,我注意到这个问题最近在 Vim 主邮件列表中出现了两次。提到了NrrwRgn plugin both times (制作两个狭窄区域并区分它们)。使用 Christian Brabandt 所描述的 NrrwRgn 感觉更像是一种变通方法而不是解决方案,但也许这已经足够了。

我试用了 NrrwRgn,它与 :diffthis 一起,对于说明单个文件部分中每个字符的差异确实很有用。但它需要多次击键。我的 Vimscript 相当生疏,但它可能是脚本化的。也许可以增强 NrrwRgn 以提供所需的功能。

想法?

【讨论】:

【参考方案2】:

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

参考示例Top 4 File Difference Tools on UNIX / Linux – Diff, Colordiff, Wdiff, Vimdiff。

【讨论】:

wdiff 很有趣,谢谢!为了澄清我最初的问题,我正在寻找能够为恰好采用统一差异格式的单个文件提供增强语法突出显示的东西。 稍微偏离主题(关于逐字比较,不增强现有的差异输出),但我发现以下组合最适合逐字可视化:* wdiff old_file new_file | cdiff * @ 987654324@,然后在 vim :windo wincmd K 中,以便从并排切换到垂直窗口布局(一个在另一个下方)。这种布局对于长行的文件要好得多。 顺便说一句,其他一些值得一试的工具,未在链接文章中提及:wdiff2mdiff 和 Google's online tool。【参考方案3】:

鉴于您在问题中对 Vim 的引用,我不确定这是否是您想要的答案 :) 但 Emacs 可以做到这一点。打开包含差异的文件,确保您在 diff-mode 中(如果文件名为 foo.difffoo.patch,这会自动发生;否则键入 Mx diff-mode RET),转到您感兴趣的大块头并点击 Cc Cbrefine-hunk。或者使用 M-n 一次遍历文件一大块;这将自动进行精炼。

【讨论】:

为我工作!呵呵,我用 Vim 已经 10 年了,但我只是安装了 emacs。 :) 但是 emacs 不支持从标准输入读取,我不能做例如git log master.. -p | emacs - @Hi-Angel 您可以打开 Emacs 并输入 M-! 以运行命令并将输出捕获到缓冲区中。【参考方案4】:

在 git 中,你可以在不提交的情况下合并。先合并你的补丁,然后做:

git diff --word-diff-regex=.

注意等号后面的点。

【讨论】:

更好:git diff --color-words=.. @ntc2 你应该让你的评论成为答案。 支持者请注意,我最初的用例假设您只有一个补丁文件,没有 git repo,甚至没有基础/修改版本。这就是我接受@legoscia 的回答的原因……它准确地描述了所要求的内容。 @ntc2 git diff --color-words=.git diff --color-words . 工作方式不同。更好的是git diff --color-words . @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 -- . 进行验证。【参考方案5】:
git diff --color-words="[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+"

上述正则表达式 (from Thomas Rast) 在标点符号/字符级别分离差异片段方面做得不错(同时不像 --word-diff-regex=. 那样嘈杂)。

我发布了结果输出 here 的屏幕截图。


更新:

This article 有一些很棒的建议。具体来说,git repo 的 contrib/ 树有一个 diff-highlight perl 脚本,它显示了细粒度的亮点。

快速开始使用:

$ 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

【讨论】:

您可以将其缩短为--color-words=[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+' 我必须将' 添加到该值的开头。否则我得到一个错误。另外,我只是使用--color-words 得到与使用该正则表达式完全相同的行为。 @gcb 文本内容很重要。如果您的更改以空格分隔,则没有区别。但是,如果您将 foo.bar 更改为 foo.qux 之类的内容,您会看到不同之处。 更简单:git diff --color-words='[^[:space:]]|([[:alnum:]]|UTF_8_GUARD)+'. 我已经用 Homebrew 安装了 git,并且已经在 /usr/local/share/git-core/contrib/diff-highlight/diff-highlight 有了那个脚本。 This 似乎暗示 Homebrew 的 git 确实将整个 contrib 安装在 /usr/local/share/git-core/contrib/ 中。所以最后,以下对我有用git diff --color=always | /usr/local/share/git-core/contrib/diff-highlight/diff-highlight【参考方案6】:

这里有一些版本的输出噪音比git diff --word-diff-regex=<re> 要少,而且它们需要的输入比git diff --color-words --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>

其中&lt;re&gt; 是一个定义“单词”的正则表达式,用于识别更改。

这些噪音较小,因为它们为更改的“单词”着色,而仅使用 --word-diff-regex=&lt;re&gt; 将匹配的“单词”与彩色的 -/+ 标记包围起来。

【讨论】:

我自己喜欢--color-words,没有=. 部分。 git diff --color-words='\w' 可以更好地使用变音符号(git v1.7.10.4) 您更复杂的版本效果很好。我附加了--word-diff=plain 以另外有[--] 环绕删除和++ 环绕添加。但是,正如手册警告的那样,源中实际出现的这些分隔符没有以任何方式转义 不幸的是,您更复杂的版本似乎没有突出显示,例如缩进改变了,我在这个上面打开了a question 这个答案很棒!但是,有没有办法将这些更改的背景实际更改为绿色/红色?【参考方案7】:

如果你不反对安装 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 的包装器......至少对于像我这样的 perlophobes 来说安装起来更容易,而且 GitHub 页面也有很好的文档记录 :)

【讨论】:

以上是关于如何在统一的差异文件中可视化每个字符的差异?的主要内容,如果未能解决你的问题,请参考以下文章

如何可视化或格式化差异/补丁文件? [关闭]

可视化两个数值数组之间的差异

是否有工具可以检查两个 callgrind/valgrind 配置文件的差异?

R语言ggplot2可视化:可视化时间序列季节图使用季节图可以比较不同年份相同月份的数据差异或者相同(年/月/周等)的时间序列在同一天的数据差异(Seasonal Plot)

WinForms 或 WPF 的文本差异可视化控件

使用 OpenCV Python 检测和可视化两个图像之间的差异