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

时间:2017-06-27 09:30:10

标签: git scripting git-diff git-blame

考虑到一系列提交,比如说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.

所以Carl改变了Bob的2行,从Bob删除了一行,并从Adam改变了一行。因此,我的脚本输出应为:

鲍勃:3 亚当:1

我的整体解决方案是:

  1. 查找更改的行范围
  2. 将这些范围与-L参数一起传递给git blame以查询前一位作者
  3. 通过解析git blame的输出并总结来完成最后的分组。
  4. 我目前正在努力争取1:获得由diff改变的线范围(在这种情况下,一个范围为3,6)。一旦我有这些范围,我可以将它们传递给git blame -L以获得这些行的先前作者。 那么如何让git diff或其他git工具将行范围作为数字start,end对返回?

1 个答案:

答案 0 :(得分:1)

我不知道告诉Git这样做的方法,但我一起解决了解析git diff输出的解决方案,以获得您需要的值。

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

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

表示从第5行开始删除2行,并在那里添加3行。 (-U0的{​​{1}}参数隐藏了所有上下文行,因此只打印实际更改的行。如果没有该参数,则行号将不正确。)可能会出现三种不同的情况。给定的块:添加行,删除行,或修改行(删除和添加)。前面的示例显示了标题将为修改的行显示的内容。添加的行看起来像这样:

git diff

对于您的用例,我们可以忽略这些行。删除的行看起来像这样:

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

请注意,每对中的第二个数字是一个偏移量,表示添加/删除了多少行。值得庆幸的是,@@ -5,5 +4,0 @@ 也可以接受git blame值的偏移量,因此我们可以将其按照<end>可以接受的格式进行处理。

这是一个单行班,应该可以解决这个问题:

git blame

说明:

  • 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中不存在的行。

    < / LI>
  • 下一个HEAD命令会删除主要状态字符。

  • 如果在给定的块中只添加或删除了一行,sed将使用例如git diff作为范围而不是+2+2,1命令修复了该问题。

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

您可以使用单行输出的每一行(保存到例如git blame),如下所示:

$row