如何改进 git 的差异突出显示?

Posted

技术标签:

【中文标题】如何改进 git 的差异突出显示?【英文标题】:How to improve git's diff highlighting? 【发布时间】:2018-08-23 00:45:51 【问题描述】:

git diff 的输出针对往往是每行一个语句的代码进行了优化,而文本可能(如果像我这样的作者懒得使用换行符)会导致 diff 输出,这很难阅读,而且更多的是“沃利呢?”搜索比读取差异输出

而在 GitLab 或 GitHub 的 Web 前端上突出显示会立即显示差异

我知道我正在比较 html 和纯文本(苹果和橙子),但是应该可以通过使用不同的颜色或在更改周围添加标记字符来改进 git diff 输出(JUnit 使用 @987654331 @ 周围的插入不太好读,但我的意思是一个例子),这将是第一次我希望在 git 中的某个地方有一些东西实际上没有。

【问题讨论】:

另见unix.stackexchange.com/questions/19317/…和unix.stackexchange.com/questions/44266/…和***.com/questions/5326008/…和***.com/questions/15458237/git-pretty-format-colors 【参考方案1】:

另一个答案中建议的word-diff 并不是 gitlab/github 所做的。要获得相同的效果,您可以使用diff-highlight 脚本,即distributed with git。

    首先找到diff-highlight 脚本的路径。它因系统而异,通常不在 $PATH 中。你可以用你的包管理器找到它,例如:

      Fedora:rpm -ql git | grep diff-highlight Debian/Ubuntu/Mint:dpkg -L git | grep diff-highlight Archlinux:pacman -Ql git | grep diff-highlight

    编辑~/.gitconfig,并将以下内容添加到[pager] 部分(替换路径)

    [pager]
        # diff-highlight is script provided by git that shows word-by-word diff
        log  = perl /usr/share/git/diff-highlight/diff-highlight | less
        show = perl /usr/share/git/diff-highlight/diff-highlight | less
        diff = perl /usr/share/git/diff-highlight/diff-highlight | less
    

    我在这里使用perl 而不是直接调用脚本,因为某些发行版似乎没有在脚本上设置可执行位。 IMO 这是一个应该报告的包错误。无论如何,这个答案应该可以忽略这一点。

现在logdiffshow 命令应该逐字显示差异。截图:

【讨论】:

我的答案与您的答案非常接近,并且正确地指出我应该删除它。您可以指示如何找到路径(find -L /usr -name diff-highlight -type f)并使脚本可执行(sudo chmod +x /usr/share/doc/git/contrib/diff-highlight/ diff-highlight)然后我会删除我的答案? @Zorglub29 好的,所以,我采纳了你的建议。我正在考虑使用find 命令和一些技巧来获得对我们来说将是/usr 的路径,并且可以在更广泛的发行版上工作。但是在我运行find /usr 之后,它在我停止它之前没有返回 10 秒,我认为使用find 是个坏主意。它很慢,而且会无缘无故地污染文件缓存。我添加了一些包管理器使用示例。关于未设置的可执行位,请注意,在 git package update 之后,您的更改将会丢失。为了解决这个问题,我直接在答案中调用perl 最近的编辑确实改进了这个答案。值得一提的是,我使用了 locate 实用程序来获取 diff-highlight 脚本的路径(它已经在最近的 Fedora 上可以执行,但在 Ubuntu 16.04 上不可用)。 在 Debian 测试 (bullseye) 中,它在 doc (?!) 中,并且没有 diff-highlight/diff-highlight;我能看到的最接近的是 diff-highlight/diff-highlight.perl 并返回此错误: Undefined subroutine &DiffHighlight::highlight_stdin called at /usr/share/doc/git/contrib/diff-highlight/diff-highlight.perl line 7 . 更新上述关于 Debian 测试的评论:cd /usr/share/doc/git/contrib/diff-highlight 然后:sudo make 我有我的可执行差异突出显示。【参考方案2】:

另外值得一提的是diffr。它是用 Rust 编写的,并使用 Myers 最长公共子序列算法。与 git 的 diff-highlight 相比,它提供了更好的结果,请参阅:

git 的diff-highlight:

diffr:

安装后,使用方法与diff-highlight类似,即编辑~/.gitconfig,在[pager]部分添加如下:

[pager]
    log  = diffr | less
    show = diffr | less
    diff = diffr | less

【讨论】:

可以确认 diffr 提供了比 diff-highlight 更好的行内变化指示。那个截图并没有卖给我,但我想做的第一件事是,整个 500 个字符的文本块被 diff-highlight 突出显示,而唯一的实际变化——两个额外的“\n”——被 diffr 突出显示。谢谢你好天使! @mlncn 欢迎您!还可以查看diffr 支持的选项,您可能有兴趣使用其中的一些。例如。我个人使用--line-numbers aligned 选项。 查看 GitHub 页面 (diffr) 进行安装。对于 Ubuntu,我安装了$ cargo install diffr,并修改了.gitconfig,如Integration with git 中所述。 [pager] 部分添加到~/.gitconfig 文件不适用于我的Ubuntu 20.04 系统。然后我安装了diffr 并按照 diffr GitHub 存储库中的说明进行操作。现在我的 git 命令可以完美地与 diffr 配合使用。谢谢@Burak @TomNguyen,也许你在 .gitconfig 的其他地方还有另一个 [pager] 部分?我不确定还有什么问题。我刚刚通过重命名旧的~/.gitconfig 并使用帖子中的唯一内容创建一个新的答案来测试我的答案,它对我有用。虽然我在 Archlinux 上进行测试,但这并不重要,与 git 配置相关的行为在发行版之间应该是相同的。【参考方案3】:

您可以使用--word-diff[=<mode>] 选项来更轻松地查看一行中哪些单词发生了变化。这在手册页中描述为

显示单词差异,使用<mode> 分隔更改的单词。默认情况下,单词由空格分隔;请参阅下面的--word-diff-regex<mode> 默认为普通,并且必须是以下之一:

color – 仅使用颜色突出显示更改的单词。暗示--color

plain – 将单词显示为[-removed-]+added+. 如果分隔符出现在输入中,则不会尝试对其进行转义,因此输出可能不明确。

porcelain – 使用一种特殊的基于行的格式供脚本使用。添加/删除/未更改的运行以通常的统一差异格式打印,从行首的+/-/` ` 字符开始并延伸到行尾。输入中的换行符由单独一行的波浪号 ~ 表示。

none – 再次禁用单词差异。

请注意,尽管第一个模式的名称是,如果启用,颜色用于突出显示所有模式中更改的部分。

【讨论】:

我尝试在我的~/.gitconfig 文件中添加一个[pager] 部分,其中包含以下行` diff = git diff --word-diff=plain --color -- "$@" | less` 但输入 git diff myFile 会打印我在 repo 中更改的所有文件的差异。当我输入 git diff anyFile 时,你有一些 ~/.gitconfig 的想法来自动化 git diff --word-diff=plain --color -- "$@" 吗?

以上是关于如何改进 git 的差异突出显示?的主要内容,如果未能解决你的问题,请参考以下文章

突出显示 OBIEE 或 SQL 中父值的子值差异

比较两个或多个 JTable 和“突出显示”差异

并排输出两个Pandas数据帧的差异 - 突出显示差异

内联代码的 R Markdown 语法突出显示的差异

Excel 公式或规则或 vba 比较 2 个单元格并仅突出显示差异

如何在 vs 代码版本控制中停止全行突出显示?