2012-07-31 95 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