如何在 git 中找到所有更改行的先前作者?



给定一系列提交,例如HEAD~1HEAD(即,只是HEAD),我想找到在该范围内更改的行的先前作者以及他们更改了多少行。

更准确地说:对于范围内更改的每一行,我想获取以前的作者(例如使用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 blamegit 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.

所以卡尔从鲍勃那里换了两行,从鲍勃那里删除了一行,从亚当那里换了一行。因此,我的脚本的输出应该是:

鲍勃: 3 亚当: 1

我的总体解决方案是:

  1. 查找更改的行范围
  2. 将这些范围与-L参数传递给git blame以查询以前的作者
  3. 通过解析git blame输出并汇总来自己进行最后的分组。

我目前正在为 1.:获取由差异更改的行范围(在本例中为一个范围 3,6)。一旦我有了这些范围,我就可以将它们传递给git blame -L,以获得这些行的先前作者。那么如何使git diff或其他 git 工具将行范围作为数字start,end对返回呢?

我不知道有什么方法可以告诉 Git 这样做,但我拼凑了一个解决方案来解析git diff的输出以获得你需要的值。

如果你运行git diff -U0,在每个块的顶部,你会看到类似这样的内容:

@@ -5,2 +5,3 @@

这意味着从第 5 行开始删除了 2 行,并在那里添加了 3 行。 (git diff-U0参数隐藏所有上下文行,以便仅打印实际更改的行。 如果没有该参数,行号将不正确。 给定的块可能发生三种不同的情况:添加了行,删除了行或修改了行(删除和添加)。 前面的示例显示了修改后的行的标题将显示的内容。 添加的行如下所示:

@@ -5,0 +6,2 @@

对于您的用例,我们可以忽略这些行。 删除的行将如下所示:

@@ -5,5 +4,0 @@

请注意,每对中的第二个数字是一个偏移量,显示添加/删除了多少行。 值得庆幸的是,git blame也可以接受<end>值的偏移量,因此我们可以将其调整为git blame可以接受的格式。

这是一个应该可以解决问题的 bash 单行代码:

git diff -U0 HEAD~1 -- $file | grep "^@@" | grep -Ev "@@ -[[:digit:]]+,0" | sed 's/^@@ //' | sed 's/ @@.*//' | cut -d' ' -f 1 | sed 's/[+-]//' | awk '{ if ($1 !~ /,/) { print $1",1" } else { print $1 } }' | sed 's/,/,+/'

解释:

  • $file是您正在处理的当前文件。

  • 第一个grep命令将输出限制为块标头,第二个grep命令删除表示添加行的块。

  • 前两个sed命令删除除范围行号之外的所有内容。

  • cut用于获取第一个范围值,即HEAD~1中存在的行,HEAD中不存在的行。

  • 下一个sed命令将去除前导状态字符。

  • 如果在给定块中只添加或删除一行,git diff将使用例如+2作为范围而不是+2,1awk命令可以解决此问题。

  • 最后,最后一个sed命令将,替换为,+,以便git blame知道第二个值是偏移量而不是行号。

您可以使用单行输出的每一行(保存为 例如$row) 如下:

git blame -L$row HEAD~1 -- $file

相关内容

  • 没有找到相关文章

最新更新