如何在 git add --patch 中使用 --color-words?

Posted

技术标签:

【中文标题】如何在 git add --patch 中使用 --color-words?【英文标题】:How to use --color-words with git add --patch? 【发布时间】:2012-06-08 02:06:46 【问题描述】:

比较文件时,我更喜欢使用git diff --color-words。有没有办法在使用git add --patchgit add --interactive 时将其设为差异的默认格式?

【问题讨论】:

如果我编辑此问题以涵盖--word-diff--color-words,是否可以?如果是这样,那么我的near 重复问题here 将能够作为该问题的exact 副本关闭。这将允许在此处合并答案,从而提高社区的效率。 可能与您可以在此处找到的内容重复:***.com/questions/49278577/…。请看看那里的答案。 【参考方案1】:

根据 VonC 所说的:

从 Git 2.9 开始,您可以在 add --patch 期间使用此命令为单词着色:

git -c interactive.diffFilter="git diff --color-words" add -p

这会将调用的interactive.diffFilter 变量设置为add -p,而不影响进一步的调用。对我来说这是理想的,因为我通常想正常运行add -p,但有时想用--color-words 运行它。

您可以像这样轻松地为此命令添加别名:

git config --global alias.addcw '-c interactive.diffFilter="git diff --color-words" add -p'

【讨论】:

很好地使用了add --patch,还有很好的别名! +1 就像已经指出的那样,答案是(可悲的)错误,因为使用的命令git diff --color-words 不会使标准输入着色,但通常会执行。只需执行echo test | git diffgit show <some-older-commit> | git diff 即可获取证据。 来自命令行工具的 macOS 上的 Git 2.17.2,我看到了 fatal: mismatched output from interactive.diffFilter hint: Your filter must maintain a one-to-one correspondence hint: between its input and output lines. @VitalyZdanevich:我也看到了。 在带有 git 2.17.1 的 Ubuntu 上出现同样的错误 fatal: mismatched output【参考方案2】:

从VonC's answer 获得启发。下面是git 2.9中引入的--interactive选项的详细使用步骤。

将diff-highlight 添加到您的路径中。

在 Ubuntu 上,diff-highlight 带有 git,可以在 /usr/share/git/diff-highlight/diff-highlight 中找到。

否则,您可以下载并手动设置。

cd ~/bin
curl -LO "https://raw.githubusercontent.com/git/git/master/contrib/diff-highlight/diff-highlight"
chmod u+x diff-highlight

如有必要,请重新启动您的 shell。

然后配置 Git 以在分页器中显示差异时过滤您的差异:

git config --global pager.log 'diff-highlight | less'
git config --global pager.show 'diff-highlight | less'
git config --global pager.diff 'diff-highlight | less'
git config --global interactive.diffFilter diff-highlight

这将额外强调一行的变化部分,这与--word-diff几乎相同。

优势是您可以在任何地方获得单词差异,例如 git log --patchgit add -p

【讨论】:

这几乎对我有用,但 URL 不再有效,所以我不得不从源代码构建diff-highlight(下载正确的 git 版本——不确定它有多重要——;cd <source directory>/contrib/diff-highlight ; 执行make; 将新的diff-highlight 添加到您的PATH) 然后从这个答案中的步骤chmod 开始。使用git version 2.17.2 (Apple Git-113) 为我工作。 你应该已经在你的 git 安装中安装了 diff-highlight。 在 Ubuntu Xenial 上,它以0644 模式安装。 Grrrr。 对于一个brew安装的git,路径是/usr/local/Cellar/git/2.27.0//share/git-core/contrib/diff-highlight/diff-highlight 你也可以通过“pip3 install --user diff-highlight”安装它,将“~/.local/bin”添加到$PATH【参考方案3】:

我最近解决了这个问题,但它需要在 git 中修改 Perl 脚本。不过,这很简单,不需要特殊技能。

此解决方案要求您的 git 配置对屏幕输出使用着色,因为这是 git 显示基于单词的差异的唯一情况。

    将安装中的git-add--interactive 复制到PATH 环境变量中的某个位置,并将其重命名为git-add--interactive-words。 编辑一行大约一半以更改*
@colored = run_cmd_pipe("git", @diff_cmd, qw(--color --), $path);

@colored = run_cmd_pipe("git", @diff_cmd, qw(--color --color-words --), $path);
    您现在可以运行 git add-interactive--words 来执行与 git add --interactive 等效的基于彩色单词的差异。 但是,将git add --patch 与它结合起来很尴尬,因为您需要向新脚本传递正确的参数。幸运的是,您可以为 .gitconfig 中的魔法词创建一个别名:
[alias]
iaddpw = add--interactive-words --patch=stage --

这意味着git iaddpw 运行与git add --interactive --patch 等效的基于彩色单词的差异。


*- 对于 Git 2.18,此命令为:

my @display_cmd = ("git", @diff_cmd, qw(--color --), $path);

【讨论】:

聪明。你应该向 Git 提交一个补丁。谢谢。 我的论文提交后;-) @mabraham 但我收到了这个警告:Use of uninitialized value $_ in print at /usr/local/Cellar/git/1.8.0/libexec/git-core/git-add--interactive-words line 1339 但使用 git add -p 并没有给我这个警告 @BPm @mabraham:您可以通过使用 if 语句将第 1339 行(即print;)包围来压制该消息,以确保定义了$_,即将第1339 行替换为if ($_) print; 行 1270-1340 中的现有着色代码假定“之前”和“之后”大块有内容,这不再一定是这种情况。 @Nevik 的修复在那里和第 1282 行有效。【参考方案4】:

使用 git 2.9(2016 年 6 月),您将拥有一个新选项:interactive.diffFilter

参见Jeff King (peff)commit 0114384(2016 年 2 月 27 日)。(由 Junio C Hamano -- gitster -- 合并于 commit 2052c52,2016 年 4 月 3 日)

add --interactive: 允许自定义差异高亮程序

add--interactive的patch hunk selector知道怎么问 git 获取彩色差异,并将它们与 我们应用的无色差异。但是没有办法 使用诸如 contrib 之类的差异过滤器工具的人 diff-highlight 以查看它们的正常突出显示。

此补丁允许用户定义任意 shell 命令以 通过管道传输彩色差异。确切的输出不应该 问题(因为我们只是向人类展示结果)只要 它与原始 diff 行兼容(因此 hunk-splitting 也可以拆分彩色版本)。

然后您可以将该差异通过管道传输到 diff --color-words

作为Andrew Dufresne的commented,GitHub blog post指的是contrib脚本contrib/diff-highlight

您可以使用“--color-words”仅突出显示更改的部分 线。然而,这对于代码来说通常很难阅读,因为它会丢失 行结构,你最终会得到格式奇怪的位。

相反,此脚本对面向行的差异进行后处理,查找对 行,并突出显示不同的段。

结果特别强调了一行的变化部分:

关于这些差异,“diff-highlight”过滤器(在contrib/)学会了更好地理解“git log --graph”输出。

参见commit 4551fbb、commit 009a81e、commit fbcf99e、commit 7ce2f4c、commit e28ae50、commit 53ab9f0、commit 5013acc(2018 年 3 月 21 日)Jeff King (peff)。(合并Junio C Hamano -- gitster --commit d19e556,2018 年 4 月 10 日)

在“diff-highlight: detect --graph by indent”中查看更多信息


注意:在 Git 2.17(Q2 2018)之前,“git add -i”使用的“interactive.diffFilter”必须保持其输入和输出的一一对应关系,但并未强制执行,导致最终用户混乱。

我们现在至少要确保过滤结果的行数与其输入的行数相同,以检测损坏的过滤器。

见commit 42f7d45、commit af3570e(2018 年 3 月 3 日)Jeff King (peff)。(由 Junio C Hamano -- gitster -- 合并到 commit c5e2df0,2018 年 3 月 14 日)


在 Git 2.30(2021 年第一季度)中,“git add -i(man) 无法使用配置为显示补丁的自定义颜色,这一问题已得到纠正。

见commit 96386fa、commit 890b68b、commit 0cb8939、commit afae3cb、commit 6681e36(2020 年 11 月 16 日)、commit 25d9e5c、commit c62cd17、commit 6f1a5ca、commit decc9ee(11 月 11 日)、2和commit cb581b1、commit d34e450(2020 年 11 月 10 日)Johannes Schindelin (dscho)。(由 Junio C Hamano -- gitster -- 合并到 commit e0d2568,2020 年 12 月 8 日)

add -p:比color.diff.plain更喜欢color.diff.context

签字人:约翰内斯·辛德林

Git 的差异机制允许用户覆盖在差异中使用的颜色,甚至是纯色的上下文行。截至8dbf3eb6850(diff.h:将DIFF_PLAIN颜色槽重命名为DIFF_CONTEXT, 2015-05-27,Git v2.4.5),配置设置的首选名称是color.diff.context,尽管Git仍然允许@987654407 @。

git add -p(man) 的上下文中,这个逻辑有点难以复制:git_diff_basic_config() 按顺序读取所有配置值,如果它看到 any em> color.diff.contextcolor.diff.plain,它接受新颜色。 不过,git add -p(man) 的 Perl 版本需要通过 git config --get-color(man),它只允许指定一个键。 git add -p(man)的内置版本也是如此,必须经过repo_config_get_value()

我们可以在这里做的最好的事情是寻找.context,如果没有找到,则回退到寻找.plain,如果仍然没有找到,则回退到硬编码的默认值(在这种情况下只是一个空字符串,因为上下文行通常没有着色)。

当使用两个配置名称时,这仍然会导致不一致:初始差异将由差异机制着色。 但是,一旦被用户编辑,大块必须由 git add -p(man) 重新着色,然后它将使用其他设置为上下文行着色。

在实践中,这并不是所有那么糟糕。 git config(man) 手册在color.diff.<slot> 中这么说:

`context` (context text - `plain` is a historical synonym)  

因此,我们应该假设用户使用其中一个名称,而不是两个名称。 此外,编辑后查看大块的情况相对较少,因为默认情况下它会立即上演。

【讨论】:

这个github tutorial 对如何使用这个新选项有更好的描述。 @Andrew-Dufresne 我同意。我已经包含了对博客文章引用的 contrib 脚本的引用。 执行 git config interactive.diffFilter diff-highlight - 现在在 git commit -p 中完全没有颜色。 git version 2.17.1 (Apple Git-112) @VitalyZdanevich 尝试使用git add -p 而不是git commit -p @VonC 不同的行。【参考方案5】:

解决方案

使用diff-highlight | less -FRX --tabs=4 作为您的diffFilter

git -c interactive.diffFilter="diff-highlight | less -FRX --tabs=4" add --patch

更多关于diff-highlight:source,a quick primer

自制

如果您使用 Homebrew (OS X),您可以将以下内容放入您的 .gitconfig(以使用已安装的 diff-highlight):

    [interactive]
        diffFilter = "$(git --exec-path | sed 's/libexec/share/')/contrib/diff-highlight/diff-highlight | less -FRX --tabs=4"

输入输出1-1对应

从 git 2.17 开始,单词 diff 解决方案必须保持输入和输出行之间的 1-1 对应关系以避免:

$ git -c interactive.diffFilter="git diff --word-diff --color" add --patch
fatal: mismatched output from interactive.diffFilter
hint: Your filter must maintain a one-to-one correspondence
hint: between its input and output lines.

diff-so-fancy 现在支持此功能(从 v1.4.0 开始),因为 https://github.com/so-fancy/diff-so-fancy/issues/35 已关闭。见this。

【讨论】:

很好地使用了interactive.diffFilter,我描述了in my own answer。 +1 macOS Mojave - No such file or directory 默认预装 git。 我只在 OS X 上测试了 Homebrew 的安装,确实如此。以下是来自git 自己的一些说明:git-scm.com/book/en/v1/…【参考方案6】:

如前所述,将diff-highlight 添加到interactive.diffFilter 配置键是最简单的选择(从Git 2.9 开始)。以下命令可以在 Debian/Ubuntu 上完成此操作,而无需复制脚本、更改权限或修改 $PATH:

git config interactive.diffFilter "perl /usr/share/doc/git/contrib/diff-highlight/diff-highlight"

git -c interactive.diffFilter="git diff --color-words" add -pgit config interactive.diffFilter "git diff --color-words" 之类的东西不能正常工作:add -p 总是提示第一个修改的文件。

【讨论】:

【参考方案7】:

这个工具做得很好https://github.com/mookid/diffr

[core]
    pager = diffr | less -R
[interactive]
    diffFilter = diffr

【讨论】:

【参考方案8】:

这也可以通过delta:

[interactive]
    diffFilter = delta --color-only --features=interactive

通过diff-so-fancy:

[interactive]
    diffFilter = diff-so-fancy --patch

【讨论】:

【参考方案9】:

在你的 $(HOME)/.gitconfig 文件中添加这个

[color]
        diff = auto
        interactive = auto

应该这样做。

【讨论】:

谢谢,但这不是我要说的。这不是 color,而是我正在寻找的逐字差异。 没有。我说的是逐个字符的差异,而不是逐行的差异。试试git diff --color-words,你就会明白我的意思了。

以上是关于如何在 git add --patch 中使用 --color-words?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用寻呼机进行长 git add --patch hunks?

使用 git add --patch <filename> 手动编辑

`Git add --patch` 多个文件:从上一个文件转到大块

不能将 git add 与 --patch 选项一起使用

[Git] Use git add --patch for better commit history and mitigating bugs

如何使用git 生成patch 和打入patch