【问题标题】:How to find the previous authors of all changed lines in git?如何在git中找到所有更改行的先前作者?
【发布时间】:2017-11-30 07:12:56
【问题描述】:

给定一系列提交,比如 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 的 1 行,并更改了 Adam 的 1 行。因此,我的脚本的输出应该是:

鲍勃:3 亚当:1

我的整体解决方案是:

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

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

【问题讨论】:

    标签: git scripting git-diff git-blame


    【解决方案1】:

    我不知道如何告诉 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 可以接受的格式。

    这里有一个 单行,应该可以解决问题:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-20
      • 2015-11-26
      • 1970-01-01
      • 1970-01-01
      • 2016-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多