Git diff仅显示已修改的行

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

+ this line is added

已删除的行:

- this line is removed

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

this line is not modified
this line is also not modified

这将导致实际的Git差异如下所示:

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

我是否可以要求Git只显示已修改的行,而忽略所有其他未修改的代码?我已经编写了一个方法,它将删除所有没有";的行。+";或";-";在他们面前签名,但我相信一定有更简单的方法来做这件事。

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

79065 次浏览

你想要的是一个有0行上下文的diff.您可以使用以下命令生成:

git diff --unified=0

git diff -U0

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

git config diff.context 0

要对任何存储库进行全局设置,请执行以下操作:

 git config --global diff.context 0

根据Chris的最新评论,后处理的主要问题是您希望保留以-|+开头的行,但您还希望过滤掉以---|+++开头的行。另一方面,如果您在repo中存储修补程序文件(我在皮杜普中存储),则您希望保留以--|++开头的行,因此regexp变得有点复杂:

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

regexp使用了一种消极的预测方法:参见Peter Boughton对这个问题的回答以获得详细的解释。

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

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

另一种方法(在UN*X上)仅显示以+-开头的行:

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

上面的代码执行以下操作:

  • git diff -U0:选择0条上下文行
  • 第一个grep仅包括以__abc0或__abc1开始的所有行
  • 第二个grep排除以__abc0或__abc1开头的行。

颜色

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

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 diff选项,如__abc0、__abc1、__abc2、__abc3等,则需要修改上述解决方案。
  • 这两个grep可以合并为一个grep -E -v '^(\+\+\+ b/|--- a/|@@ |diff --git|index )',但我发现双grep版本更容易理解。

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

$ 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

就像我上面说的,这只是在大多数情况下。如果将输出通过管道传输到abc0__文件,然后尝试相同的regex,它将不起作用。

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

无论如何,希望这对你的情况有所帮助。

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

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字符。

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

git diff -U0 --color=always HEAD~ | grep --color=never -E $'^\e\[(32m\+|31m-)'
  1. -U0表示在更改的行周围包含0行上下文,即:仅包含更改的行本身。参见man git diff
  2. grep的__abc0允许它使用扩展正则表达式。
  3. $''语法显然允许ANSI引用,这可以正确地解释ESC(转义或0x1B)字符。参见在这里
  4. 下面是https://www.regex101.com的正则表达式描述:enter image description here
  5. 基本上,^匹配行的开始,\e匹配转义字符,转义字符是终端中的颜色代码的开始,\[匹配颜色代码中的下一个字符,下一个字符是[,然后(this|that)语法匹配“ this ”或“ that ”,其中“ this ”是32m+,它是绿色+行,31m-是一条红线。
  6. 颜色是这样的:\e[32m是绿色,\e[31m是红色。
  7. 当然,+显示由git diff标记为添加的行,而-显示由git diff标记为删除的行。
  8. 注意,在第二grep表达式中,--color=never必需的,以防止其突出显示其匹配,否则将破坏从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差异(带行号的Git日志)
  2. 【别人的回答】带行号的Git差异(带行号的Git日志)
  3. 使用行号和正确的代码对齐/缩进进行Git比较
  4. git-filechange-search.sh-一个脚本,允许您在文件中搜索变量或函数名,并确定哪个承诺包含该变量或函数名的更改。例如,用法:./git-filechange-search.sh path/to/my/file.cpp variable_name将查找所有对file.CPP进行更改且其中包含variable_name承诺。这对于查看某些功能的更改位置和时间非常有用。这就好像它是一个搜索,可以随着时间的推移通过git blame来观察文件的各个部分。

我是否可以要求Git只显示已修改的行,而忽略所有其他未修改的代码?

以及从行动计划在主要答复下的后续评论

感谢您的快速回复。这解决了我一半的问题,但我仍然得到一些行,比如diff中的__abc0和git diff顶部的__abc1.-r3b00t.

为了解决上述两个要求,下面是使用git-diffc.shawk-基于语言的包装器的单行解决方案,我围绕git diff编写:

git diffc

完成!

以下是git diffc的特征。
所有这些特征合在一起,在这里解决所有其他答案的缺点:

  1. 它处理彩色和非彩色输出。这就是这个正则表达式的作用:__abc0
  2. 它可以处理所有颜色和所有文本格式选项,包括粗体,斜体,删除线等,您可以__ABC 3。这就是上面的正则表达式中包含;?{1,10}的原因:如果它检测到颜色或文本格式化代码的开始,它将匹配这些组合的ANSI代码的最多10个序列。
  3. 它也不像已接受的答案那样包括以@@和字diff开始的行。如果您确实需要这些行(坦率地说,我认为这些行很有用:)),请执行以下操作:
    git diff --unified=0
    
    git diff -U0
    
  4. 它以与git diff完全相同的方式显示输出:在具有可选颜色输出(-R)的less分页器中,并且仅当文本为>;时。1页(-F),同时在qUIT(-X)时保留屏幕上的当前文本页面。

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

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 diffChanges";,意思是:只显示代码的改变了行,没有其他内容。我写的。它不是普通Git的一部分。

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

在这里下载:git-diffc.sh。它是我的ercaguy_dotfiles回购的一部分。

要安装它:

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添加到您的PATH变量。如果注销并重新登录不起作用,请将以下几行代码添加到~/.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.

其他安装注意事项:

另请参阅我关于git diffn的另一个答案的安装部分,我也写在这里。不过,在这些指令中看到git-diffn的地方,请使用git-diffc。这也包括__中的ABC3命令。下载和安装git diffc非常简单:只需几个命令。

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

下面的代码组成了git diffc包装器。

这里没有任何一个其他答案(包括我的另一个答案)会100%正确地执行您想要的操作。然而,这个答案将。下面是一个可以复制并粘贴到终端的1行程序。我只是把它做成了多行,以提高可读性——你可以用任何一种方式复制粘贴它,所以我也可以让它具有可读性!,它依赖于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

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

  1. gawk(GNUawk)手册: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
  3. 如果你也想要git diffn,它是带有行号的git diff,请看这里:带行号的Git差异(带行号的Git日志)
  4. 一些awk";hello world";语法测试示例:https://github.com/electricrcaircraftguy/ercaguy_hello_world/tree/master/awk

作为奖励,我还将上述内容打包用作git diffc,它的意思是Git diff只显示' C '变化";。用法是完全相同git diff;只需使用git diffc即可!它支持所有选项。默认情况下,颜色处于启用状态。要关闭它,只需使用git diffc --no-colorgit diffc --color=never。有关详细信息,请参见man git diff

因为我昨晚刚刚完成了git diffn(一个用行' n '数字显示git diff的工具),所以编写git diffc是微不足道的。我想我最好趁知识还在我脑子里的时候现在就做。