Git diff仅显示已修改的行


128

当我执行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中,我只想查看已被修改的行。

提前致谢。

Answers:


182

您想要的是带有0行上下文的差异。您可以使用以下方法生成此代码:

git diff --unified=0

要么

git diff -U0

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

git config diff.context 0

要为任何存储库全局设置它:

 git config --global diff.context 0

4
感谢您的快速回复。这解决了我一半的问题,但是我的差异中仍然出现“ @@ -1 +1 @@”这样的行,而git diff的顶部仍然有“ diff --git a / db / xxxxxxx b / db / xxxx索引” xxxxx..aaaaaaa bbbbbbbb
r3b00t

3
我认为git没有提供任何避免输出这些行的方法,因为如果没有它们,差异就没有意义(您不知道正在查看哪个文件,也不知道文件在何处)。
克里斯·海斯

8
@Rakesh:为进行扩展,git-diff尝试创建实际上可以用作源文件补丁的diff,而没有这些信息是不可能的。删除它的唯一方法是自己对其进行后处理,例如via git diff | egrep "^(\+|-) "
克里斯·海斯

1
git config --global diff.context 0 将其设置在全球范围内
Andrzej Rehmann

如果要在特定目录中查看,请尝试git diff -U0 <dir>
Eswar Yaganti

41

另一个技巧(在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/行首出现的限制已删除,以适应转义序列,这可能会导致边缘情况。

补充笔记:

  • 将上述溶液需要修改如果使用附加git的差异选项,例如-R--src-prefix--dst-prefix--no-prefix,等。
  • 可以将这两个组合并为一个grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )',但我发现双grep版本更容易理解。

2
好一个。支持对每个过滤器的明确说明。
henrebotha

我看到许多以git diff“ header”开头的行@@,但是git diff---或开头的行是什么+++?我不知道那些。
加布里埃尔·斯台普斯

啊没关系。那些表示包含添加(+++)或删除(---)的文件的文件名。我现在在这里看到:git-scm.com/docs/git-diff#_combined_diff_format
加布里埃尔·斯台普斯

再次更正:--- a/filename似乎表示“左侧的文件”或以前的文件,并且+++ b/filename似乎表示“右侧的文件”或现在进行了更改的文件。我非常习惯git difftool与meld一起使用,它显示了漂亮的并排比较,以至于我从来没有真正习惯过看git diff,所以对我来说仍然很陌生,而且我以前从未真正看过这些细微差别。
加布里埃尔·斯台普斯

1
@GabrielStaples,已添加对颜色的支持。谢谢。
user650654

6

在跟进Chris的最新评论之后,后期处理的主要问题是您希望保留以开头的行,-|+但您也想过滤掉以开头的行---|+++。另一方面,如果您将修补程序文件存储在存储库中(我在Pydoop中这样做),则您希望保留以开头的行--|++,因此regexp会涉及到一些问题:

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

正则表达式使用否定的前瞻:有关详细说明,请参见Peter Boughton对这个问题的回答。

如果您经常这样做,则可能要为其设置一个git别名:

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

1
这在Windows git bash上对我不起作用。不知道为什么(grep说无效的选项P),此刻还没有内容。
丹尼斯

1
-P--perl-regexp用于将模式解释为Perl常规表达式,但并不总是实现。它在OSX上对我不起作用。gnu.org/software/grep/manual/grep.html#grep-Programs
Willington Vega

5

我认为在简单的情况下,正则表达式可以更短,更容易记住,但需要注意的是,如果在行本身以+或开头的行中进行了更改,则此行将不起作用-

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

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


例:

$ cat testfile
A
B
C
D
E
F
G

说我变成CXE变成了YG变成了Z

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

就像我上面说的,这只是在大多数情况下。如果将输出通过管道传输到file dout,然后尝试使用相同的正则表达式,则将无法正常工作。

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

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


对于行以“-”开头的情况,它将行不通。示例:- name: No pdb在yaml文件中。
anapaulagomes '18 -10-26

3

该答案将保留原始的红色/绿色以提高可读性。我提供了一些语法变化:

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需要,以防止混帐从禁用当管道的颜色。
  • grep --color=never是为了防止grep删除原始颜色并突出显示匹配的字符串。
  • 我们匹配以红色(\e[31m)或绿色(\e[32m)换码开头的行。
  • $'...'(ANSI-C引用语法)或-P(perl的语法)是让grep解释\e\033作为ESC字符。

谢谢你 这是我刚想到的另一种形式。您的工作$''对我特别有帮助。stackoverflow.com/a/61929887/4561887
Gabriel Staples

1

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

这里的其他答案(包括我的其他答案)中没有一个可以完全正确地完成您想要的100%的操作。但是,此答案将会。这是一个1-liner,您可以复制并粘贴到终端中。我已将其设置为多行以提高可读性-您可以使用相同的方式将其复制粘贴,这样我也可以使其可读!它依赖于awk编程语言:

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. 它处理所有颜色和所有文本格式选项,包括粗体,斜体,删除线等,您可以git config设置中进行设置。这就是为什么上述正则表达式具有;?{1,10}它:如果它检测到的颜色或文本格式代码的开始,它将匹配到这些组合ANSI编码的10个序列。
  3. 它也不包括以@@和开头的行diff,就像公认的答案一样。如果您确实想要这些行(坦率地说,我认为这是有用的:)),请执行以下操作:

    git diff --unified=0
    

    要么

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

由于它使用awk编程语言,因此它还具有功能强大且易于配置的优点。

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

  1. gawk(GNU awk)手册:https : //www.gnu.org/software/gawk/manual/html_node/index.html#SEC_Contents
  2. 研究git diffn及其中的评论:https : //github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles/blob/master/useful_scripts/git-diffn.sh
    1. 如果你想git diffn太多,这是git diff行号,在这里看到:行号git的差异(行号的Git日志)
  3. 一些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 diffngit diff用“ n'umbers” 显示的工具)以来,写作git diffc是微不足道的。我以为我现在最好在知识不新鲜的情况下这样做。

安装git diffc

请按照此处答案末尾说明进行操作,但git-diffn在说明中无处不,请git-diffc改用。这也包括在wget命令中。下载和安装git diffc很容易:仅需几个命令。


0

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

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. -U0说,包括0线改线周围背景的-即:只包括改变线本身。请参阅man git diff
  2. -E对grep的允许工作与扩展正则表达式
  3. $''语法显然允许使用ANSI引号,从而可以正确解释ESC(转义,或0x1b)字符。看这里
  4. 这是来自https://www.regex101.com的正则表达式描述:在此处输入图片说明
  5. 基本上,^匹配行的开头,\e匹配Escape字符,这是终端中颜色代码的开始,\[匹配颜色代码中的下一个字符,即[,然后(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仅显示已修改的行
  3. @wisbucky的回答:Git diff仅显示已修改的行

有关:

  1. [我自己的答案] 带行号的Git diff(带行号的Git日志)
  2. [别人的答案] Git diff与行号(Git日志与行号)
  3. git diff与行号和正确的代码对齐/缩进
  4. git-filechange-search.sh-一个脚本,该脚本使您可以在文件中搜索变量或函数名称,并找出哪些提交包含对该变量或函数名称的更改。例如 用法:./git-filechange-search.sh path/to/my/file.cpp variable_name将查找其中包含对file.cpp所做的更改的所有提交variable_name。这对于查看某些功能的更改时间和地点很有用。好像这是一次搜索,可以观察git blame随着时间的推移显示的文件的各个部分。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.