【问题标题】:Git contributors of each file每个文件的 Git 贡献者
【发布时间】:2012-07-29 01:49:41
【问题描述】:

我想列出存储库中每个文件的每个贡献者。

这是我目前的工作:

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

这很慢。有没有更好的解决方案?

【问题讨论】:

    标签: git sh


    【解决方案1】:

    以ДМИТРИЙ的回答为基础,我想说的是:

    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)则行为正确

    【讨论】:

    • 与igor答案相比,这相当慢。我们有一个巨大的存储库。每个文件需要几秒钟。
    【解决方案2】:

    我会编写一个小脚本来分析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,这意味着它相当快。缺点:它是一个单独的脚本。

    【讨论】:

    • 这个速度很快,但它不会报告完整的文件路径。
    • 如果您的目录结构太深以至于文件名被截断,只需为 --stat 选项指定任意高输出宽度参数,例如--stat=1000
    • --stat=1000,1000 完成了这项工作
    • Nobody: " " igor: 这是一个 perl 脚本!
    【解决方案3】:

    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-tree 获取存储库中的所有跟踪文件。 Find 真是个糟糕的选择。

      例如,获取当前目录(./)中分支master 中的跟踪文件列表:

      git ls-tree -r --name-only master ./
      
    2. 您可以使用get shortlog 获取文件编辑器列表(git blame 是矫枉过正):

      git shortlog -s -- $file
      

    因此,对于来自ls-tree 响应的每个文件,您应该调用shortlog 并根据需要修改其输出。

    【讨论】:

    • +1,这是正确的方法,但是它不遵循文件重命名,如果文件名包含空格,它会失败。请参阅我的答案以解决此问题
    【解决方案4】:

    git log --pretty=format:"%cn" &lt;filename&gt; | sort | uniq -c

    您还可以使用git log 做更多事情,例如:在特定日期之后提交每个文件(例如:2018-10-1 之后): git log --after="2018-10-1" --pretty=format:"%cn" &lt;filename&gt; | sort | uniq -c

    参考:https://www.atlassian.com/git/tutorials/git-log

    【讨论】:

    • 这并不能回答 OP 的问题,OP 希望对每个文件都这样做,并且只想遍历历史记录一次,而不是每个文件一次。
    【解决方案5】:

    如果您不需要统计信息,请不要使用--stat,为什么要求它重新运行所有差异,然后刮掉所有结果?只需使用--name-only

    git log --all --pretty=%x09%cN --name-only |  awk -F$'\t' '
            NF==2   { name=$2 }
            NF==1   { contribs[ $0 ][ name ] = 1 }
            END     {
                    n = asorti(contribs,sorted)
                    for ( i=0 ; ++i < n ; ) {
                            file = sorted[i]
                            print file
                            for ( name in contribs[file] ) print "\t"name
                    }
            }
    '
    

    【讨论】:

      猜你喜欢
      • 2014-10-16
      • 2012-11-06
      • 2014-01-30
      • 2011-09-13
      • 2013-01-24
      • 2015-08-14
      • 2010-12-24
      • 2014-04-15
      • 2021-12-10
      相关资源
      最近更新 更多