2017-06-27 66 views
1

给定一系列的提交,比如HEAD~1HEAD(即只是HEAD),我想查找以前的那些在那个范围内被改变的行的作者以及他们改变了多少行。如何查找git中所有更改行的以前作者?

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

所以卡尔改变2号线从鲍勃,删除一行从鲍勃,并从亚当改变一行。因此,我的脚本的输出应该是:

鲍勃:3 亚当:1级

我的整体的解决方案是:

  1. 找到改变的线范围
  2. 通过这些范围与-L参数git blame来查询以前的作者
  3. 通过解析git blame的输出和总结我自己做最后的分组。

我目前正在努力争取1:得到差异更改的行范围(在这种情况下一个范围3,6)。一旦我有这些范围,我可以将它们传递给git blame -L以获得这些行的以前的作者。 那么我怎样才能让git diff或其他的git工具返回线性范围为数字start,end对?

回答

1

我不知道有办法告诉Git这样做,但我一起砍了一个解决方案来解析git diff的输出以获取所需的值。

如果运行git diff -U0,在每个块的顶部,你会看到这样的事情:

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

这意味着两行被删除开始第5行,并加入3那里。 (参数-U0 隐藏所有上下文行,以便只打印实际更改的行,如果没有该参数,行号将不正确)。对于给定的块可能会发生三种不同的情况:添加了行,行被删除,或行被修改(删除&添加)。前面的例子显示了标题对修改过的行显示的内容。新增线路是这样的:

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

  • 下一个sed命令会去掉前导状态字符。

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

  • 最后,最后sed命令替换,,+使得git blame知道第二值的偏移,而不是一个行号。

可以使用一个衬垫的输出的每一行(保存到例如$row)如下:

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