2017-06-27 65 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