如何找到 git 中所有更改行的先前作者?
How to find the previous authors of all changed lines in git?
给定一系列提交,比如 HEAD~1
和 HEAD
(即,只有 HEAD
),我想找到 previous 作者在该范围内更改的行数以及更改的行数。
更准确地说:对于范围内更改的每一行,我想获得以前的作者(例如,使用 git blame
)。然后我想按这些作者总结更改的行。
例如,考虑HEAD
之前被这些人改过的文件X(我在行首标记了改行的人,相当于git blame
的输出):
Adam: Lorem ipsum dolor
Adam: sit amet, consectetur
Adam: adipiscing elit.
Bob: Praesent efficitur urna
Bob: ac volutpat lacinia.
Bob: Sed sagittis, metus non
Adam: maximus tristique, leo
Adam: augue venenatis enim,
Adam: ac rutrum nulla odio
Adam: id urna.
现在,作者 Carl
将文件更改如下(请注意,这是 git blame
和 git diff
的伪代码混合):
Adam: Lorem ipsum dolor
Adam: sit amet, consectetur
- Adam: adipiscing elit.
+ Carl: adipiscing elit I love cats.
- Bob: Praesent efficitur urna
+ Carl: Praesent efficitur urna :D
- Bob: ac volutpat lacinia.
+ Carl: ac volutpat lacinia YOLO.
+ Carl: Added extra line, lol!
- Bob: Sed sagittis, metus non
Adam: maximus tristique, leo
Adam: augue venenatis enim,
Adam: ac rutrum nulla odio
Adam: id urna.
所以 Carl 更改了 Bob 的 2 行,删除了 Bob 的 1 行,并更改了 Adam 的 1 行。因此,我的脚本的输出应该是:
鲍勃:3
亚当:1
我的整体解决方案是:
- 查找更改的行范围
- 将这些范围与
-L
参数一起传递给 git blame
以查询以前的作者
- 通过解析
git blame
的输出并总结自己进行最终分组。
我目前正在努力解决 1.:获取由 diff 更改的行范围(在本例中为一个范围 3,6)。一旦我有了这些范围,我就可以将它们传递给 git blame -L
以获取这些行的先前作者。 那么我如何制作 git diff
或其他 git 工具 return 行范围作为数字 start,end
对?
我不知道告诉 Git 这样做的方法,但我拼凑了一个解决方案来解析 git diff
的输出以获得您需要的值。
如果你 运行 git diff -U0
,在每个块的顶部你会看到这样的东西:
@@ -5,2 +5,3 @@
这意味着从第 5 行开始删除了 2 行,并在那里添加了 3 行。 (git diff
的 -U0
参数隐藏所有上下文行,因此只打印实际更改的行。如果没有该参数,行号将不正确。)可能会出现三种不同的情况给定的块:添加行、删除行或修改行(删除和添加)。前面的示例显示了 header 将对修改后的行显示的内容。添加的行将如下所示:
@@ -5,0 +6,2 @@
对于您的用例,我们可以忽略这些行。删除的行将如下所示:
@@ -5,5 +4,0 @@
请注意,每对中的第二个数字是一个偏移量,显示有多少行 added/removed。值得庆幸的是,git blame
也可以接受 <end>
值的偏移量,因此我们可以将其修改为 git blame
可以接受的格式。
这里有一个 bash one-liner 应该可以解决问题:
git diff -U0 HEAD~1 -- $file | grep "^@@" | grep -Ev "@@ -[[:digit:]]+,0" | sed 's/^@@ //' | sed 's/ @@.*//' | cut -d' ' -f 1 | sed 's/[+-]//' | awk '{ if ( !~ /,/) { print ",1" } else { print } }' | sed 's/,/,+/'
解释:
$file
是您正在处理的当前文件。
第一个 grep
命令将输出限制为块 headers,第二个 grep
命令删除表示添加行的块。
前两个 sed
命令删除除范围行号以外的所有内容。
cut
用于获取第一个范围值,即 HEAD~1
中存在但 HEAD
.[=40 中不存在的行=]
下一个 sed
命令去除前导状态字符。
如果在给定的块中只添加或删除一行,git diff
将使用例如+2
作为范围而不是 +2,1
。 awk
命令修复了这个问题。
最后,最后的sed
命令将,
替换为,+
,这样git blame
就知道第二个值是一个偏移量而不是一行数.
您可以使用 one-liner 输出的每一行(例如保存到 $row
),如下所示:
git blame -L$row HEAD~1 -- $file
给定一系列提交,比如 HEAD~1
和 HEAD
(即,只有 HEAD
),我想找到 previous 作者在该范围内更改的行数以及更改的行数。
更准确地说:对于范围内更改的每一行,我想获得以前的作者(例如,使用 git blame
)。然后我想按这些作者总结更改的行。
例如,考虑HEAD
之前被这些人改过的文件X(我在行首标记了改行的人,相当于git blame
的输出):
Adam: Lorem ipsum dolor
Adam: sit amet, consectetur
Adam: adipiscing elit.
Bob: Praesent efficitur urna
Bob: ac volutpat lacinia.
Bob: Sed sagittis, metus non
Adam: maximus tristique, leo
Adam: augue venenatis enim,
Adam: ac rutrum nulla odio
Adam: id urna.
现在,作者 Carl
将文件更改如下(请注意,这是 git blame
和 git diff
的伪代码混合):
Adam: Lorem ipsum dolor
Adam: sit amet, consectetur
- Adam: adipiscing elit.
+ Carl: adipiscing elit I love cats.
- Bob: Praesent efficitur urna
+ Carl: Praesent efficitur urna :D
- Bob: ac volutpat lacinia.
+ Carl: ac volutpat lacinia YOLO.
+ Carl: Added extra line, lol!
- Bob: Sed sagittis, metus non
Adam: maximus tristique, leo
Adam: augue venenatis enim,
Adam: ac rutrum nulla odio
Adam: id urna.
所以 Carl 更改了 Bob 的 2 行,删除了 Bob 的 1 行,并更改了 Adam 的 1 行。因此,我的脚本的输出应该是:
鲍勃:3 亚当:1
我的整体解决方案是:
- 查找更改的行范围
- 将这些范围与
-L
参数一起传递给git blame
以查询以前的作者 - 通过解析
git blame
的输出并总结自己进行最终分组。
我目前正在努力解决 1.:获取由 diff 更改的行范围(在本例中为一个范围 3,6)。一旦我有了这些范围,我就可以将它们传递给 git blame -L
以获取这些行的先前作者。 那么我如何制作 git diff
或其他 git 工具 return 行范围作为数字 start,end
对?
我不知道告诉 Git 这样做的方法,但我拼凑了一个解决方案来解析 git diff
的输出以获得您需要的值。
如果你 运行 git diff -U0
,在每个块的顶部你会看到这样的东西:
@@ -5,2 +5,3 @@
这意味着从第 5 行开始删除了 2 行,并在那里添加了 3 行。 (git diff
的 -U0
参数隐藏所有上下文行,因此只打印实际更改的行。如果没有该参数,行号将不正确。)可能会出现三种不同的情况给定的块:添加行、删除行或修改行(删除和添加)。前面的示例显示了 header 将对修改后的行显示的内容。添加的行将如下所示:
@@ -5,0 +6,2 @@
对于您的用例,我们可以忽略这些行。删除的行将如下所示:
@@ -5,5 +4,0 @@
请注意,每对中的第二个数字是一个偏移量,显示有多少行 added/removed。值得庆幸的是,git blame
也可以接受 <end>
值的偏移量,因此我们可以将其修改为 git blame
可以接受的格式。
这里有一个 bash one-liner 应该可以解决问题:
git diff -U0 HEAD~1 -- $file | grep "^@@" | grep -Ev "@@ -[[:digit:]]+,0" | sed 's/^@@ //' | sed 's/ @@.*//' | cut -d' ' -f 1 | sed 's/[+-]//' | awk '{ if ( !~ /,/) { print ",1" } else { print } }' | sed 's/,/,+/'
解释:
$file
是您正在处理的当前文件。第一个
grep
命令将输出限制为块 headers,第二个grep
命令删除表示添加行的块。前两个
sed
命令删除除范围行号以外的所有内容。cut
用于获取第一个范围值,即HEAD~1
中存在但HEAD
.[=40 中不存在的行=]下一个
sed
命令去除前导状态字符。如果在给定的块中只添加或删除一行,
git diff
将使用例如+2
作为范围而不是+2,1
。awk
命令修复了这个问题。最后,最后的
sed
命令将,
替换为,+
,这样git blame
就知道第二个值是一个偏移量而不是一行数.
您可以使用 one-liner 输出的每一行(例如保存到 $row
),如下所示:
git blame -L$row HEAD~1 -- $file