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

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

【问题讨论】:

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

标签: git


【解决方案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”安装它,并在 $PATH 中添加“~/.local/bin”
【解决方案3】:

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

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

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

@colored = run_cmd_pipe("git", @diff_cmd, qw(--color --color-words --), $path);
  1. 您现在可以运行 git add-interactive--words 来执行与 git add --interactive 等效的基于彩色单词的差异。
  2. 但是,将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 DufresnecommentedGitHub blog post指的是contrib脚本contrib/diff-highlight

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

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

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

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

参见commit 4551fbbcommit 009a81ecommit fbcf99ecommit 7ce2f4ccommit e28ae50commit 53ab9f0commit 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 42f7d45commit 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 96386facommit 890b68bcommit 0cb8939commit afae3cbcommit 6681e36(2020 年 11 月 16 日)、commit 25d9e5ccommit c62cd17commit 6f1a5cacommit decc9ee(11 月 11 日)、2和commit cb581b1commit 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 的差异机制允许用户覆盖在差异中使用的颜色,甚至是纯色的上下文行。截至8dbf3eb6850diff.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-highlightsourcea 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
      

      【讨论】:

      • 感谢您提及 2022 年的可行解决方案。
      【解决方案9】:

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

      [color]
              diff = auto
              interactive = auto
      

      应该这样做。

      【讨论】:

      • 谢谢,但这不是我要说的。这不是 color,而是我正在寻找的逐字比较。
      • 没有。我说的是逐个字符的差异,而不是逐行的差异。试试git diff --color-words,你就会明白我的意思了。
      猜你喜欢
      • 2012-12-24
      • 2011-08-03
      • 1970-01-01
      • 2018-08-10
      • 2010-11-28
      • 2013-07-23
      • 2017-02-06
      • 2013-01-07
      相关资源
      最近更新 更多