【问题标题】:Git diff to show only lines that have been modifiedGit diff 仅显示已修改的行
【发布时间】:2013-09-19 13:49:45
【问题描述】:

当我执行 git diff 时,它会显示已添加的行:

+ this line is added

已删除的行:

- this line is removed

但它也显示了许多未修改的行:

this line is not modified
this line is also not modified

这导致实际的 git diff 看起来像这样:

+ this line is added
  this line is not modified
- this line is removed
  this line is not modified

我可以要求 git 只显示已修改的行并忽略所有其他未修改的代码吗?我写了一个方法,可以删除前面没有“+”或“-”号的所有行,但我相信一定有更简单的方法来做到这一点。

在我的 git diff 中,我只对查看已修改的行感兴趣。

【问题讨论】:

标签: git diff


【解决方案1】:

你想要的是一个 0 行上下文的差异。您可以使用以下方法生成它:

git diff --unified=0

git diff -U0

您还可以将其设置为该存储库的配置选项:

git config diff.context 0

要全局设置,适用于任何存储库:

 git config --global diff.context 0

【讨论】:

  • 感谢您的快速回复。这解决了我的一半问题,但我仍然在我的 diff 中得到一些像“@@ -1 +1 @@”这样的行,而我的 git diff 顶部有“diff --git a/db/xxxxxxx b/db/xxxx index xxxxx..aaaaaaa bbbbbbbb
  • 我认为 git 没有提供任何方法来避免输出这些行,因为没有它们,差异就没有意义(你不知道你在看哪个文件,也不知道你在哪里文件)。
  • @Rakesh:为了扩展,git-diff 尝试创建实际上可以用作源文件补丁的差异,如果没有这些信息,这是不可能的。删除它的唯一方法是自己进行后处理,例如通过git diff | egrep "^(\+|-) "
  • git config --global diff.context 0 全局设置
  • 如果您想在特定目录中查看,请尝试 git diff -U0
【解决方案2】:

另一个 hack(在 un*x 上)只显示以 +- 开头的行:

git diff -U0 | grep '^[+-]' | grep -Ev '^(--- a/|\+\+\+ b/)'

上面的代码做了以下事情:

  • git diff -U0: 选择 0 个上下文行
  • 第一个 grep 仅包括以 +- 开头的所有行
  • 第二个 grep 排除以 --- a/+++ b/ 开头的行

颜色

要显示彩色差异,请尝试以下操作:

git diff -U0 --color | grep '^\e\[[^m]*m[-+]' | grep -Ev '(--- a/|\+\+\+ b/)'
  • 表达式 ^\e\[[^m]*m[-+] 查找行首 (^),然后是转义字符 (\e),然后是 [,它们一起开始转义序列,然后是任何不是 " m”(数字、分号或什么都没有),后跟一个结束转义序列的“m”。
  • 请注意,以下所有转义序列都是有效的转义序列:\e[0m(重置)、\e[m(也重置)、\e[1m(粗体)、\e[31m(红色)、\e[32m(绿色) ,\e[9;31m(删除线+红色),\e[31;9m(红色+删除线),\e[1;4;9;31m(粗体+下划线+删除线+红色)。默认的 git 颜色使用红色和绿色,但可以重新配置。
  • --color--color=always 相同。
  • 为了适应转义序列,已取消对 --- a/+++ b/ 出现在行首的限制,这可能会导致边缘情况。

附加说明:

  • 如果使用-R--src-prefix--dst-prefix--no-prefix等额外的git diff选项,上述解决方案需要修改。
  • 两个 grep 可以组合成一个 grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )',但我发现双 grep 版本更容易理解。

【讨论】:

  • 不错的一个。赞成每个过滤器的清晰解释。
  • 我看到很多以@@ 开头的git diff "header" 类型的行,但是以---+++ 开头的git diff 行是什么?我不知道那些。
  • 啊,没关系。这些表示包含添加 (+++) 或删除 (---) 的文件的文件名。我现在在这里看到:git-scm.com/docs/git-diff#_combined_diff_format.
  • 再次更正:--- a/filename 似乎表示“左边的文件”,或以前的文件,+++ b/filename 似乎表示“右边的文件”,或文件与您的更改一样。我已经习惯了使用git difftool with meld,它显示了漂亮的并排比较,我从来没有真正习惯于看git diff,所以它对我来说仍然很奇怪,我从来没有真正看过这些细微差别之前。
  • @GabrielStaples,已添加对颜色的支持。谢谢。
【解决方案3】:

我认为对于简单的情况,正则表达式可以更短且更容易记住,但需要注意的是,如果行本身以 +- 开头的行发生更改,这将不起作用

$ git diff | grep '^[+|-][^+|-]'

正则表达式表示该行应以+- 开头,紧随其后的字符不应是这两个字符。无论我是否在这里逃脱了+,我都得到了相同的结果,顺便说一句...


例子:

$ cat testfile
A
B
C
D
E
F
G

假设我将C 更改为X,将E 更改为Y,并将G 更改为Z

$ git diff | grep '^[+|-][^+|-]'
-C
+X
-E
+Y
-G
+Z

不过,就像我上面所说的,这仅适用于大多数情况。如果您将该输出通过管道传输到文件dout,然后尝试相同的正则表达式,它将不起作用。

$ git diff dout | grep '^[+|-][^+|-]'
$

无论如何,希望对您有所帮助

【讨论】:

  • 对于以“-”开头的行将不起作用。示例:- name: No pdb 在 yaml 文件中。
【解决方案4】:

根据 Chris 的最新评论,后处理的主要问题是您希望保留以 -|+ 开头的行,但您还想过滤掉以 ---|+++ 开头的行。另一方面,如果您将补丁文件存储在您的 repo 中(我在 Pydoop 中),那么您希望保留以 --|++ 开头的行,因此正则表达式变得有点复杂:

git diff | grep -P '^\+(?:(?!\+\+))|^-(?:(?!--))'

正则表达式使用否定前瞻:有关详细说明,请参阅 Peter Boughton 对this question 的回答。

如果你经常这样做,你可能想为它设置一个 git 别名:

git config --global alias.diffonly '!git diff | grep -P "^\+(?:(?!\+\+))|^-(?:(?!--))"'

【讨论】:

  • 这在 Windows git bash 上对我不起作用。不知道为什么(grep 说选项 P 无效),目前没有胆量去研究它。
  • -P--perl-regexp 用于将模式解释为 Perl 正则表达式,但并不总是实现。它在 OSX 上对我不起作用。 gnu.org/software/grep/manual/grep.html#grep-Programs
【解决方案5】:

为了便于阅读,此答案将保留原始的红色/绿色。我提供了一些语法变化:

git diff --color | grep --color=never $'^\e\[3[12]m'
git diff --color | grep --color=never $'^\033\[3[12]m'
git diff --color | grep --color=never -P '^\e\[3[12]m'
git diff --color | grep --color=never -P '^\033\[3[12]m'

解释:

  • git diff --color 用于防止 git 在管道时禁用颜色。
  • grep --color=never 是为了防止 grep 删除原始颜色并突出显示匹配的字符串。
  • 我们正在匹配以红色 (\e[31m) 或绿色 (\e[32m) 转义码开头的行。
  • $'...'(ANSI-C 引用语法)或-P(perl 语法)是让grep\e\033 解释为ESC 字符。

【讨论】:

【解决方案6】:

这是另一种更简单的方法,只查找已修改的行,因此以单个 +- 开头,同时保留颜色输出:

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. -U0 表示在更改的行周围包含 0 行上下文 - 即:仅包含更改的行本身。见man git diff
  2. grep 的-E 允许它使用扩展的正则表达式
  3. $'' 语法显然允许 ANSI 引用,它可以正确解释 ESC(转义或 0x1b)字符。见here
  4. 这是来自https://www.regex101.com 的正则表达式描述:
  5. 基本上,^ 匹配行首,\e 匹配 Escape 字符,即终端中颜色代码的开头,\[ 匹配颜色代码中的下一个字符,即@ 987654343@,然后(this|that)语法匹配“this”或“that”,其中“this”是32m+,是绿色+线,31m-是红色-线。
  6. 颜色如下:\e[32m 是绿色,\e[31m 是红色。
  7. 当然,+ 将带有 git diff 标记的行显示为已添加,- 将带有 git diff 标记的行显示为已删除。
  8. 请注意,--color=never 在第二个 grep 表达式中是必需,以防止它突出显示其匹配项,否则会将来自 git diff 的颜色代码搞砸到离开了。
  9. + 也必须转义为\+,否则+ 是一个特殊的正则表达式 (regex) 字符,它指定 前面元素出现一次或多次。见这里:https://en.wikipedia.org/wiki/Regular_expression#Basic_concepts

参考资料:

  1. https://git-scm.com/docs/git-diff#_combined_diff_format
  2. @user650654 回答:Git diff to show only lines that have been modified
  3. @wisbucky 回答:Git diff to show only lines that have been modified

相关:

  1. [我自己的回答]Git diff with line numbers (Git log with line numbers)
  2. [别人的回答]Git diff with line numbers (Git log with line numbers)
  3. git diff with line numbers and proper code alignment/indentation
  4. git-filechange-search.sh - 一个脚本,允许您在文件中搜索变量或函数名称,并找出哪些 commits 包含对该变量或函数名称的更改。前任。用法:./git-filechange-search.sh path/to/my/file.cpp variable_name 将查找所有 commits,其中包含对 file.cpp 的更改,其中包含 variable_name。这对于查看某些功能的更改地点和时间很有用。就好像它是一种搜索,可以随着时间的推移观察通过git blame 显示的文件部分。

【讨论】:

    【解决方案7】:

    使用 git-diffc.sh awk-基于语言的包装器的 1 行解决方案,我围绕 git diff 编写:

    git diffc
    

    完成!

    git diff 8d4d4fd3b60f200cbbb87f2b352fb097792180b2~2..8d4d4fd3b60f200cbbb87f2b352fb097792180b2~3 的示例输出:

    diff --git a/useful_scripts/rg_replace.sh b/useful_scripts/rg_replace.sh
    index 74bc5bb..0add69d 100755
    --- a/useful_scripts/rg_replace.sh
    +++ b/useful_scripts/rg_replace.sh
    @@ -2,12 +2,11 @@
     
     # This file is part of eRCaGuy_dotfiles: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles
     
    -# STATUS: functional and ready-to-use
    -
    +# WORK IN PROGRESS! <===========
     # This is a simple wrapper around RipGrep (`rg`) to allow in-place find-and-replace, since the
     # `rg --replace` option replaces only the stdout, NOT the contents of the file.
     # `man rg` under the `--replace` section states: "Neither this flag nor any other ripgrep
    -# flag will modify your files." This wrapper overcomes that limitation.
    +# flag will modify your files."
     
     # INSTALLATION INSTRUCTIONS:
     # 1. Install RipGrep: https://github.com/BurntSushi/ripgrep#installation
    

    相对于git diffc 8d4d4fd3b60f200cbbb87f2b352fb097792180b2~2..8d4d4fd3b60f200cbbb87f2b352fb097792180b2~3 的示例输出。请注意,仅显示 -+ 行,而周围的上下文行消失了,并且所有其他行(例如 diffindex---+++@@)也消失了!:

    -# STATUS: functional and ready-to-use
    -
    +# WORK IN PROGRESS! <===========
    -# flag will modify your files." This wrapper overcomes that limitation.
    +# flag will modify your files."
    

    git diffc 代表“git diff changes”,意思是:只显示更改 行代码,没有别的。我写的。它不是常规 git 的一部分。

    它支持git diff 支持的所有选项和参数,因为它只是git diff 的轻量级包装器。

    在此处下载:git-diffc.sh。它是我的eRCaGuy_dotfiles repo 的一部分。

    要安装它:

    git clone https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles.git
    cd eRCaGuy_dotfiles/useful_scripts
    mkdir -p ~/bin
    ln -si "${PWD}/git-diffc.sh" ~/bin/git-diffc
    

    如果这是您第一次创建或使用~/bin 目录,现在手动注销并立即重新登录,以使 Ubuntu 的默认~/.profile 文件将~/bin 添加到您的@987654356 @ 多变的。如果注销并重新登录不起作用,请将以下几行代码添加到您的 ~/.profile 文件中,然后注销 Ubuntu 并重新登录:

    # set PATH so it includes user's private bin if it exists
    if [ -d "$HOME/bin" ] ; then
        PATH="$HOME/bin:$PATH"
    fi
    

    就是这样!

    用法:git diff。例如:

    git diffc
    git diffc -h
    git diffc commit1 commit2
    git diffc --no-color
    # etc.
    

    附加安装说明:

    See also the installation section of my other answer about git diffn, which I also wrote, here。除了在这些说明中看到git-diffn 的任何地方,请改用git-diffc。这也包括在wget 命令中。下载和安装git diffc 很简单:只需几个命令。

    如何使用awk 只显示+- 行,考虑到git diff 可能输出的任何颜色或文本格式:

    下面的这段代码构成了git diffc 包装器。

    这里没有一个其他答案(包括my other answer)能100% 正确地做到你想要的。然而,这个答案会。这是一个 1-liner,您可以将其复制并粘贴到您的终端中。 为了便于阅读,我只是将它设置为多行——你可以复制粘贴,所以我不妨让它可读!它依赖于awk 编程语言: p>

    git diff --color=always "$@" | awk '
    # 1. Match and then skip "--- a/" and "+++ b/" lines
    /^(\033\[(([0-9]{1,2};?){1,10})m)?(--- a\/|\+\+\+ b\/)/ {
        next 
    } 
    # 2. Now print the remaining "+" and "-" lines ONLY! Note: doing step 1 above first was required or
    # else those lines would have been matched by this matcher below too since they also begin with 
    # the "+" and "-" symbols.
    /^(\033\[(([0-9]{1,2};?){1,10})m)?[-+]/ {
        print $0 
    }
    ' | less -RFX
    

    这是它的特点。所有这些特点结合起来,解决了这里所有其他答案的缺点:

    1. 它处理彩色和非彩色输出。这就是这个正则表达式的作用:^(\033\[(([0-9]{1,2};?){1,10})m)?

    2. 它处理所有颜色和所有文本格式选项,包括粗体、斜体、删除线等,您可以set in your git config settings。这就是为什么上面的正则表达式中有;?{1,10} 的原因:如果它检测到颜色或文本格式代码的开头,它将匹配最多10 个这些组合的ANSI 代码序列。

    3. 它不包括以@@ 和单词diff 开头的行,就像accepted answer 那样。如果您确实想要这些行(坦率地说,我认为它们很有用:)),请改为这样做:

       git diff --unified=0
      

        git diff -U0
    
    1. 它以与git diff 完全相同的方式显示输出:在具有可选颜色输出的less 寻呼机中(-R),并且仅当文本大于1 页时(-F),并且当你quit(-X)时,屏幕上保留当前页面的文字。

    它还具有强大和易于配置的优点,因为它使用 awk 编程语言。

    如果你有兴趣学习awk,这里有一些资源:

    1. gawk (GNU awk) 手册:https://www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
    2. 研究git diffn 和其中的cmets:https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    3. 如果你也想要git diffn,即带有行号的git diff,请参见此处:Git diff with line numbers (Git log with line numbers)
    4. 一些 awk "hello world" 和语法测试示例:https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world/tree/master/awk

    作为奖励,我还将上面的内容包装起来用作git diffc,这意味着“git diff 只显示'c'hanges”。用法与git diff相同;只需使用 git diffc 代替!它支持所有选项。颜色默认为开启。要关闭它,只需使用git diffc --no-colorgit diffc --color=never。详情请见man git diff

    由于我昨晚刚刚完成了git diffn(一个显示git diff 行'数字'的工具),所以写git diffc 是微不足道的。我想我现在最好趁着知识还新鲜的时候去做。

    【讨论】:

    • diffc 从什么版本开始可用?
    • @SridharSarnobat,它不是git 的一部分。我用 awk 编程语言写了git diffc,作为对git diff 的简单包装。现在在我的答案顶部查看我的安装说明。我刚刚更新了这个答案。你也应该看看git diffn,我也写了。它更有用。
    • 啊,我明白了,谢谢你的澄清。
    猜你喜欢
    • 1970-01-01
    • 2014-10-19
    • 2011-04-24
    • 1970-01-01
    • 2015-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多