2012-07-31 79 views
8

我想列出存儲庫中每個文件的每個貢獻者。每個文件的Git貢獻者

這是目前我做的:

find . | xargs -L 1 git blame -f | cut -d' ' -f 2-4 | sort | uniq 

這是非常緩慢的。有更好的解決方案嗎?

回答

4

我會寫一個小腳本來分析git log --stat --pretty=format:'%cN'的輸出;沿着線的東西:

#!/usr/bin/env perl 

my %file; 
my $contributor = q(); 

while (<>) { 
    chomp; 
    if (/^\S/) { 
     $contributor = $_; 
    } 
    elsif (/^\s*(.*?)\s*\|\s*\d+\s*[+-]+/) { 
     $file{$1}{$contributor} = 1; 
    } 
} 

for my $filename (sort keys %file) { 
    print "$filename:\n"; 
    for my $contributor (sort keys %{$file{$filename}}) { 
     print " * $contributor\n"; 
    } 
} 

(書面只是快;不包括像二進制文件的情況。)

如果您保存這個腳本,例如,作爲~/git-contrib.pl,你可以用叫它:

git log --stat=1000,1000 --pretty=format:'%cN' | perl ~/git-contrib.pl 

優點:只需撥打git一次,這意味着它相當快。缺點:它是一個單獨的腳本。

+0

這很快,但它不報告完整的文件路徑。 – log0 2012-08-02 09:56:04

+0

如果您的目錄結構很深以便文件名被切斷,只需爲'--stat'選項指定一個任意的高輸出寬度參數,例如'--stat = 1000' – igor 2012-08-02 10:00:47

+0

'--stat = 1000,1000'做過這個工作 – log0 2012-08-02 11:51:13

2

tldr

for file in `git ls-tree -r --name-only master ./`; do 
    echo $file 
    git shortlog -s -- $file | sed -e 's/^\s*[0-9]*\s*//' 
done 
  1. 你可以在庫中的所有文件跟蹤與git ls-treeFind是非常糟糕的選擇。

    例如,在當前目錄(./)獲得分支master跟蹤文件的列表:

    git ls-tree -r --name-only master ./ 
    
  2. 你可以得到get shortlog文件的編輯列表(git blame是矯枉過正):

    git shortlog -s -- $file 
    

因此,對於ls-tree響應中的每個文件,應該調用shortlog和mod ify它的輸出,但你想要的。

+0

+ 1,這是正確的方法,但它不遵循文件重命名,並且如果文件名包含空格,它將失敗。查看我的答案以解決此問題 – CharlesB 2012-07-31 13:33:48

5

以ДМИТРИЙ的回答爲基礎,我會說以下內容:

git ls-tree -r --name-only master ./ | while read file ; do 
    echo "=== $file" 
    git log --follow --pretty=format:%an -- $file | sort | uniq 
done 

增強是它遵循文件的命名在它的歷史,其行爲是否正確文件包含空格(| while read file

+0

這個和igor的答案相比相當慢。我們有一個巨大的存儲庫。這需要每個文件幾秒鐘。 – log0 2012-08-02 10:01:03