SO 上下文中的问题:从 git diff 中找出更改的行号
基于上面的问题,我需要以git
这种格式打印两个修订版之间修改文件的差异:
/path/to/file
startline1-startline2
startline3-startline4
/path/to/another/file
startline5-startline6
...
这是我的试图过滤git
diff 的输出。
git diff --unified=0 --diff-filter=M HEAD~1 HEAD | \
grep -v -e '^[+-]' -e '^index' | \
sed 's/diff --git a.* b\//\//g; s/.*@@\(.*\)@@.*/\1/g; s/^ -//g; s/,[0-9]*//g; s/\(^[0-9]*\) +/\1-/g;'
我不确定上述命令是否满足git diff
输出中可能显示的所有情况。
现有的解决方案是否可以改进,或者是否有更好的方法可以使用其他实用程序(例如awk
或git
本身)来实现此目的?
# Using git diff [expected output w.r.t line numbers and not formatting]
$ git diff --unified=0 --diff-filter=M HEAD~3 HEAD | grep -v -e '^[+-]' -e '^index'
diff --git a/lib/get-config.js b/lib/get-config.js
@@ -89,0 +90,5 @@ module.exports = {
diff --git a/lib/pull.js b/lib/pull.js
@@ -62 +62 @@ module.exports = class Pull {
@@ -83 +83 @@ module.exports = class Pull {
diff --git a/lib/router.js b/lib/router.js
@@ -3,0 +4 @@ const yaml = require('js-yaml')
@@ -125,0 +127 @@ module.exports = app => {
@@ -136,0 +139 @@ module.exports = app => {
# Using external diff as suggested by @muru
# [expected output with formatting but line numbers don't match with git diff's output]
$ git -c diff.external='./foo.sh' diff --diff-filter=M 'HEAD~3' HEAD
/tmp/AAAA_get-config.js
90-89
/tmp/BBBB_pull.js
62
83
/tmp/CCCC_router.js
4-3
126-125
137-136
文件的行号不同router.js
。
存储库用于比较。
我想澄清一下输出中预期的格式。
git diff
生成统一 diff 格式的输出。格式是这样的:
# Assumes --unified=0 i.e no context lines
diff --git a/path/to/file b/path/to/file
index x..z mode
--- a/path/to/file
+++ b/path/to/file
@@ -l1,s +l2,s @@ optional section heading
- ...
- ...
+ ...
+ ...
diff --git a/path/to/file1 b/path/to/file1
index y..z mode
--- a/path/to/file1
+++ b/path/to/file2
@@ -l3,s +l4,s @@ optional section heading
- ...
- ...
+ ...
+ ...
.
.
.
预期的输出应仅包含已修改文件的 diff(使用--diff-filer=M
),并且应采用以下格式:
/path/to/file
l1-l2
/path/to/file1
l3-l4
l5-l6
.
.
.
这里l1
,l2
...是统一 diff 格式 ( @@ -l1,s +l2,s @@
) 中提到的行号。
@穆鲁的 回答几乎解决了问题,但使用此更改的组格式获得的行号'%df%(f=l?:-%dl)\n'
与统一 diff 格式中的行号不匹配。
有没有办法使用诸如 之类的选项来表示行号(以统一差异格式)changed-group-format
?
这是一个 MVCE 使用bash git 存储库
使用git diff
,
$ git diff --unified=0 --diff-filter=M 9e49d ad1b3 | grep -v -e '^[+-]' -e '^index'
diff --git a/execute_cmd.c b/execute_cmd.c
@@ -567 +567 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
@@ -753,2 +753 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
@@ -759,2 +758 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
@@ -1104 +1102 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
diff --git a/patchlevel.h b/patchlevel.h
@@ -28 +28 @@
diff --git a/subst.c b/subst.c
@@ -5339 +5339 @@ clear_fifo_list ()
@@ -5345 +5345 @@ copy_fifo_list (sizep)
@@ -5411,7 +5411,2 @@ unlink_fifo_list ()
@@ -5433 +5428 @@ close_new_fifos (list, lsize)
@@ -5437 +5431,0 @@ close_new_fifos (list, lsize)
@@ -5445,2 +5439,2 @@ close_new_fifos (list, lsize)
@@ -5568 +5562 @@ clear_fifo_list ()
@@ -5572 +5566 @@ copy_fifo_list (sizep)
@@ -5578 +5572 @@ copy_fifo_list (sizep)
@@ -5583 +5577 @@ copy_fifo_list (sizep)
@@ -5656 +5650 @@ close_new_fifos (list, lsize)
@@ -5660 +5653,0 @@ close_new_fifos (list, lsize)
@@ -5668,2 +5661,2 @@ close_new_fifos (list, lsize)
diff --git a/subst.h b/subst.h
@@ -276,2 +276,3 @@ extern void unlink_fifo __P((int));
预期产出
/execute_cmd.c
567-567
753-753
759-758
1104-1102
/patchlevel.h
28-28
/subst.c
5339-5339
5345-5345
5411-5411
5433-5428
5437-5431
5445-5439
5568-5562
5572-5566
5578-5572
5583-5577
5656-5650
5660-5653
5668-5661
/subst.h
276-276
# Line numbers which don't match the expected output is indicated by "#"
$ git -c diff.external='../foo.sh' diff --diff-filter=M 9e49d ad1b3
/tmp/2wJaWf_execute_cmd.c
567
753-754 #
759-760 #
1104 #
/tmp/7j19Ob_patchlevel.h
28
/tmp/fQDY8b_subst.c
5339
5345
5411-5417 #
5433 #
5437 #
5445-5446 #
.
.
.
答案1
如果你使用 GNU diff,你可以得到类似的东西,并调用git diff
它:
foo.sh
#! /bin/bash
# See https://stackoverflow.com/a/255212/2072269 for details on parameters
echo "$2" # print filename
diff --changed-group-format $'%df%(f=l?:-%dl)\n' --line-format='' "$2" "$5"
echo
exit 0
并且(例如使用bash git 存储库):
$ export GIT_EXTERNAL_DIFF="$PWD/foo.sh"
$ git diff HEAD 'HEAD^^'
execute_cmd.c
567
753-754
759-760
1104
patchlevel.h
28
subst.c
5339
5345
5411-5417
5433
5437
5445-5446
5568
5572
5578
5583
5656
5660
5668-5669
subst.h
276-277
这GNUdiff
选项:
--changed-group-format=
格式
这些行组是包含两个文件中的行的块。
%df
和%dl
是旧文件中更改组的f
第一个和最后一个行号(以十进制表示)。是一个三元表达式,比较and并忽略最后一行(如果与第一行相同)。l
d
%(f=l?:-%dl)
f
l
我们不需要实际的行,因此--line-format
设置为空。
根据 MCVE,似乎:
- 您不需要
%(f=l?:-%dl)
三元检查(如果第二个数字与第一个数字相同,则省略第二个数字)。我们只需要打印第二个数字。 - 在大多数情况下,第二个数字应该是
%F
新文件中更改的第一行。除了刚刚从旧文件中删除行的情况外,因此新文件中的行数为 0。在这种情况下,打印的数字是%E
- 新文件中组之前的行号。三元则变为%(N=0?%dE:%dF)
. - 我应该使用
$1
文件名而不是$2
.
因此,通过这些更改:
#! /bin/bash
# See https://stackoverflow.com/a/255212/2072269 for details on parameters
echo "$1" # print filename
diff --changed-group-format $'%df-%(N=0?%dE:%dF)\n' --line-format='' "$2" "$5"
echo
exit 0
这给出了预期的输出:
$ PAGER=cat git diff --unified=0 --diff-filter=M 9e49d ad1b3
execute_cmd.c
567-567
753-753
759-758
1104-1102
patchlevel.h
28-28
subst.c
5339-5339
5345-5345
5411-5411
5433-5428
5437-5431
5445-5439
5568-5562
5572-5566
5578-5572
5583-5577
5656-5650
5660-5653
5668-5661
subst.h
276-276