当前位置:  开发笔记 > 编程语言 > 正文

如何计算Git存储库中特定作者更改的总行数?

如何解决《如何计算Git存储库中特定作者更改的总行数?》经验,为你挑选了16个好方法。

是否有一个我可以调用的命令,它将计算Git存储库中特定作者更改的行?我知道必须有方法来计算提交次数,因为Github会为其影响图执行此操作.



1> Alex..:

这提供了有关作者的一些统计信息,根据需要进行修改

使用Gawk:

git log --author="_Your_Name_Here_" --pretty=tformat: --numstat \
| gawk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s removed lines: %s total lines: %s\n", add, subs, loc }' -

在Mac OSX上使用Awk:

git log --author="_Your_Name_Here_" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -

编辑(2017)

在github上有一个新的包看起来很光滑,并使用bash作为依赖(在linux上测试).它更适合直接使用而不是脚本.

这是git-quick-stats(github链接).

复制git-quick-stats到文件夹并将文件夹添加到路径.

mkdir ~/source
cd ~/source
git clone git@github.com:arzzen/git-quick-stats.git
mkdir ~/bin
ln -s ~/source/git-quick-stats/git-quick-stats ~/bin/git-quick-stats
chmod +x ~/bin/git-quick-stats
export PATH=${PATH}:~/bin

用法:

git-quick-stats

在此输入图像描述


感谢这个可爱的长衬里!这个awk斑点擦拭了每个人的甲板(准确,快速,没有额外的奇怪输出).这并不奇怪,考虑到这就是awk的设计目的......太糟糕了,你这么晚才参加聚会.
这很棒,但我不得不将`gawk`更改为`awk`以使其在OSX终端中正常工作
@ zxq9:当问到这个问题时我甚至都没有在stackoverflow,我在这里得到了答案的启发.让我们希望我会慢慢超过这里的每个人,因为人们一直需要这个.
如果该网址不适合您,请尝试以下操作:`git clone https:// github.com / arzzen / git-quick-stats.git`

2> CB Bailey..:

以下命令的输出应该相当容易发送到脚本以添加总计:

git log --author="" --oneline --shortstat

这为当前HEAD上的所有提交提供了统计信息.如果你想在其他分支中添加统计数据,你必须提供它们作为参数git log.

对于传递给脚本,甚至可以使用空日志格式删除"oneline"格式,并且由JakubNarębski评论,--numstat是另一种选择.它生成每个文件而不是每行统计信息,但更容易解析.

git log --author="" --pretty=tformat: --numstat


如果你想更容易地添加统计数据,你可以使用`--numstat`而不是`--shortstat`.
对不起这个问题,但有什么数字告诉我?有两排,我不知道他们告诉我什么.线路变得稀少和添加?
可能也想在那里添加"--no-merges".
什么是--pretty = tformat do vs. --pretty = format?
改变了我接受的答案,因为这会以我期望的方式提供输出,并且对于希望实现此目的的其他访问者将更有帮助.
@ Informatic0re`git help log`告诉我,第一行是添加的行,第二行是删除的。

3> Dan..:

如果有人想看到他们的代码库中每个用户的统计数据,我的几个同事最近提出了这个可怕的单行:

git log --shortstat --pretty="%cE" | sed 's/\(.*\)@.*/\1/' | grep -v "^$" | awk 'BEGIN { line=""; } !/^ / { if (line=="" || !match(line, $0)) {line = $0 "," line }} /^ / { print line " # " $0; line=""}' | sort | sed -E 's/# //;s/ files? changed,//;s/([0-9]+) ([0-9]+ deletion)/\1 0 insertions\(+\), \2/;s/\(\+\)$/\(\+\), 0 deletions\(-\)/;s/insertions?\(\+\), //;s/ deletions?\(-\)//' | awk 'BEGIN {name=""; files=0; insertions=0; deletions=0;} {if ($1 != name && name != "") { print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net"; files=0; insertions=0; deletions=0; name=$1; } name=$1; files+=$2; insertions+=$3; deletions+=$4} END {print name ": " files " files changed, " insertions " insertions(+), " deletions " deletions(-), " insertions-deletions " net";}'

(花几分钟时间来处理我们的仓库,它有大约10-15k的提交.)


棒极了!`michael ,:6057文件更改,854902插入(+),26973删除( - ),827929 net`
这是唯一一个为存储库提供总结果并且没有任何插件运行的命令.
@BenSewards你可以使用适用于Linux的Windows子系统在Windows上使用Bash,更多信息[这里](https://msdn.microsoft.com/commandline/wsl/about)

4> Ciro Santill..:

Git成名 https://github.com/oleander/git-fame-rb

是一个很好的工具,可以同时获取所有作者的计数,包括提交和修改的文件数:

sudo apt-get install ruby-dev
sudo gem install git_fame
cd /path/to/gitdir && git fame

还有https://github.com/casperdcl/git-fame的 Python版本(@fracz提到):

sudo apt-get install python-pip python-dev build-essential 
pip install --user git-fame
cd /path/to/gitdir && git fame

样本输出:

Total number of files: 2,053
Total number of lines: 63,132
Total number of commits: 4,330

+------------------------+--------+---------+-------+--------------------+
| name                   | loc    | commits | files | percent            |
+------------------------+--------+---------+-------+--------------------+
| Johan Sørensen         | 22,272 | 1,814   | 414   | 35.3 / 41.9 / 20.2 |
| Marius Mathiesen       | 10,387 | 502     | 229   | 16.5 / 11.6 / 11.2 |
| Jesper Josefsson       | 9,689  | 519     | 191   | 15.3 / 12.0 / 9.3  |
| Ole Martin Kristiansen | 6,632  | 24      | 60    | 10.5 / 0.6 / 2.9   |
| Linus Oleander         | 5,769  | 705     | 277   | 9.1 / 16.3 / 13.5  |
| Fabio Akita            | 2,122  | 24      | 60    | 3.4 / 0.6 / 2.9    |
| August Lilleaas        | 1,572  | 123     | 63    | 2.5 / 2.8 / 3.1    |
| David A. Cuadrado      | 731    | 111     | 35    | 1.2 / 2.6 / 1.7    |
| Jonas Ängeslevä        | 705    | 148     | 51    | 1.1 / 3.4 / 2.5    |
| Diego Algorta          | 650    | 6       | 5     | 1.0 / 0.1 / 0.2    |
| Arash Rouhani          | 629    | 95      | 31    | 1.0 / 2.2 / 1.5    |
| Sofia Larsson          | 595    | 70      | 77    | 0.9 / 1.6 / 3.8    |
| Tor Arne Vestbø        | 527    | 51      | 97    | 0.8 / 1.2 / 4.7    |
| spontus                | 339    | 18      | 42    | 0.5 / 0.4 / 2.0    |
| Pontus                 | 225    | 49      | 34    | 0.4 / 1.1 / 1.7    |
+------------------------+--------+---------+-------+--------------------+

但要注意:正如Jared在评论中所提到的那样,在一个非常大的存储库上进行它需要几个小时.不确定是否可以改进,考虑到它必须处理如此多的Git数据.


@Vincent当前用户的toal loc/commits/files的百分比.
还有[python中的git成名](https://pypi.python.org/pypi/git-fame/1.1.0).

5> mmrobins..:

我发现以下内容对于查看当前代码库中包含最多行的人员非常有用:

git ls-files -z | xargs -0n1 git blame -w | ruby -n -e '$_ =~ /^.*\((.*?)\s[\d]{4}/; puts $1.strip' | sort -f | uniq -c | sort -n

其他答案主要集中在提交中更改的行,但如果提交无法生存并被覆盖,则可能只是流失.上面的咒语也会让你所有提交者按行排序,而不是一次只有一个.您可以为git blame(-C -M)添加一些选项,以获得一些更好的数字,以便将文件移动和文件之间的行移动考虑在内,但是如果这样做,命令可能会运行更长时间.

此外,如果您要查找所有提交的所有提交中更改的行,则以下小脚本很有用:

http://git-wt-commit.rubyforge.org/#git-rank-contributors


我准备给+1,但后来我意识到解决方案取决于红宝石...... :(
对我不起作用:-e:1:在`
'中:UTF-8中的无效字节序列(ArgumentError)
您可以将其修改为不容易使用ruby,因为我只使用ruby进行字符串替换.你可以使用perl,sed,python等

6> Jakub Narębs..:

要计算给定分支上给定作者(或所有作者)的提交次数,您可以使用git-shortlog ; 特别参见它--numbered--summary选项,例如在git仓库上运行时:

$ git shortlog v1.6.4 --numbered --summary
  6904  Junio C Hamano
  1320  Shawn O. Pearce
  1065  Linus Torvalds
    692  Johannes Schindelin
    443  Eric Wong


啊,不,我错过了"在git存储库上运行时".公平地说,大多数人*不会在git repo上运行此命令.实际上,相当大的余地.
`git shortlog -sne`或者,如果你不想包括合并`git shortlog -sne --no-merges`
-1它没有回答这个问题
请注意,在此示例中,`v1.6.4`是为了使输出具有确定性:无论何时从git存储库进行克隆和/或获取,它都是相同的.

7> Jared Burrow..:

在看了AlexGerty3000的答案后,我试图缩短单线:

基本上,使用git log numstat并且跟踪已更改的文件数.

Mac OSX上的Git版本2.1.0:

git log --format='%aN' | sort -u | while read name; do echo -en "$name\t"; git log --author="$name" --pretty=tformat: --numstat | awk '{ add += $1; subs += $2; loc += $1 - $2 } END { printf "added lines: %s, removed lines: %s, total lines: %s\n", add, subs, loc }' -; done

例:

Jared Burrows   added lines: 6826, removed lines: 2825, total lines: 4001



8> Erik Zivkovi..:

来自AaronM的使用shell 单行的答案是好的,但实际上,还有另一个错误,如果用户名和日期之间有不同数量的空格,空格将破坏用户名.损坏的用户名将为用户计数提供多行,您必须自己总结它们.

这个小改动为我解决了这个问题:

git ls-files -z | xargs -0n1 git blame -w --show-email | perl -n -e '/^.*?\((.*?)\s+[\d]{4}/; print $1,"\n"' | sort -f | uniq -c | sort -n

注意+ after后面会消耗从名称到日期的所有空格.

实际上添加这个答案对我自己的记忆和帮助其他人一样多,因为这至少是我第二次谷歌主题:)

编辑2019-01-23添加--show-emailgit blame -w电子邮件聚合,因为有些人Name在不同的计算机上使用不同的格式,有时两个同名的人在同一个git中工作.



9> kccqzy..:

这是一个简短的单行程序,为所有作者生成统计数据.它比上面的Dan解决方案快得多,速度为/sf/ask/17360801/(我的时间复杂度为O(N)而不是O(NM),其中N是提交数,M是作者数).

git log --no-merges --pretty=format:%an --numstat | awk '/./ && !author { author = $0; next } author { ins[author] += $1; del[author] += $2 } /^$/ { author = ""; next } END { for (a in ins) { printf "%10d %10d %10d %s\n", ins[a] - del[a], ins[a], del[a], a } }' | sort -rn


很好,但输出意味着什么?
ins [a] - del [a],ins [a],del [a],a,所以如果我是正确的插入 - 删除,插入,删除,名称

10> Stéphane Gou..:

@mmrobins @AaronM @ErikZ @JamesMishra提供的变体都有一个共同的问题:他们要求git生成一个不用于脚本消费的信息混合,包括来自同一行上的存储库的行内容,然后将该混乱与正则表达式匹配.

当某些行不是有效的UTF-8文本时,以及当某些行恰好与正则表达式匹配时(这发生在这里),这是一个问题.

这是一条没有这些问题的修改过的行.它要求git在不同的行上干净地输出数据,这样可以很容易地过滤我们想要的内容:

git ls-files -z | xargs -0n1 git blame -w --line-porcelain | grep -a "^author " | sort -f | uniq -c | sort -n

你可以grep其他字符串,如author-mail,committer等.

也许首先export LC_ALL=C(假设bash)强制执行字节级处理(这也恰好可以从基于UTF-8的语言环境中大大加快grep).



11> AaronM..:

在中间给出了ruby的解决方案,perl在默认情况下更加可用,这是作者对当前行使用perl的替代方案.

git ls-files -z | xargs -0n1 git blame -w | perl -n -e '/^.*\((.*?)\s*[\d]{4}/; print $1,"\n"' | sort -f | uniq -c | sort -n


更新的正则表达式并没有产生有意义的差异,并且因为你没有逃脱第一个paren而被打破.但是,我可以看到一些情况,我前一个可能会在代码行中找到一些要锁定的位.这样可以更可靠地工作:git ls-files -z | xargs -0n1 git blame -w | perl -n -e'/^.*?\\((.*?)\s[\d]{4}/; print $ 1,"\n"'| sort -f | uniq -c | sort -n

12> Esko Luontol..:

除了Charles Bailey的回答,您可能还想将-C参数添加到命令中.否则,文件重命名计为大量添加和删除(尽管文件有行数),即使文件内容未被修改也是如此.

为了说明,这里是一个提交,在使用git log --oneline --shortstat命令时,我的一个项目会移动大量文件:

9052459 Reorganized project structure
 43 files changed, 1049 insertions(+), 1000 deletions(-)

这里使用git log --oneline --shortstat -C检测文件副本和重命名的命令进行相同的提交:

9052459 Reorganized project structure
 27 files changed, 134 insertions(+), 85 deletions(-)

在我看来,后者提供了一个更真实的视图,了解一个人对项目的影响,因为重命名文件比从头开始编写文件要小得多.


当我执行"git log --oneline --shortstat"时,我没有获得你的结果.我有一个提交列表,其中包含版本数,但不包括总数.如何获得在所有git存储库中编辑的总行数?

13> Nevir..:

这是一个快速的ruby脚本,可以根据给定的日志查询来确定每个用户的影响.

例如,对于rubinius:

Brian Ford: 4410668
Evan Phoenix: 1906343
Ryan Davis: 855674
Shane Becker: 242904
Alexander Kellett: 167600
Eric Hodel: 132986
Dirkjan Bussink: 113756
...

剧本:

#!/usr/bin/env ruby

impact = Hash.new(0)

IO.popen("git log --pretty=format:\"%an\" --shortstat #{ARGV.join(' ')}") do |f|
  prev_line = ''
  while line = f.gets
    changes = /(\d+) insertions.*(\d+) deletions/.match(line)

    if changes
      impact[prev_line] += changes[1].to_i + changes[2].to_i
    end

    prev_line = line # Names are on a line of their own, just before the stats
  end
end

impact.sort_by { |a,i| -i }.each do |author, impact|
  puts "#{author.strip}: #{impact}"
end


这个脚本很棒,但不包括只有单行提交的作者!要修复,请更改如下:更改= /(\ d +)插入.*(\ d +)删除/ .match(行)

14> 小智..:

你可以使用whodid(https://www.npmjs.com/package/whodid)

$ npm install whodid -g
$ cd your-project-dir

$ whodid author --include-merge=false --path=./ --valid-threshold=1000 --since=1.week

或者只是输入

$ whodid

然后你可以看到这样的结果

Contribution state
=====================================================
 score  | author
-----------------------------------------------------
 3059   | someguy 
 585    | somelady 
 212    | niceguy 
 173    | coolguy 
=====================================================



15> 小智..:

这是最好的方法,它还可以让您清楚地了解所有用户提交的总数

git shortlog -s -n



16> AaronM..:

我在上面提供了一个简短答案的修改,但它不足以满足我的需求.我需要能够在最终代码中对提交的行和行进行分类.我也希望按文件分解.此代码不会递归,它只会返回单个目录的结果,但如果有人想要更进一步,这是一个良好的开端.复制并粘贴到文件中并生成可执行文件或使用Perl运行它.

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $dir = shift;

die "Please provide a directory name to check\n"
    unless $dir;

chdir $dir
    or die "Failed to enter the specified directory '$dir': $!\n";

if ( ! open(GIT_LS,'-|','git ls-files') ) {
    die "Failed to process 'git ls-files': $!\n";
}
my %stats;
while (my $file = ) {
    chomp $file;
    if ( ! open(GIT_LOG,'-|',"git log --numstat $file") ) {
        die "Failed to process 'git log --numstat $file': $!\n";
    }
    my $author;
    while (my $log_line = ) {
        if ( $log_line =~ m{^Author:\s*([^<]*?)\s*<([^>]*)>} ) {
            $author = lc($1);
        }
        elsif ( $log_line =~ m{^(\d+)\s+(\d+)\s+(.*)} ) {
            my $added = $1;
            my $removed = $2;
            my $file = $3;
            $stats{total}{by_author}{$author}{added}        += $added;
            $stats{total}{by_author}{$author}{removed}      += $removed;
            $stats{total}{by_author}{total}{added}          += $added;
            $stats{total}{by_author}{total}{removed}        += $removed;

            $stats{total}{by_file}{$file}{$author}{added}   += $added;
            $stats{total}{by_file}{$file}{$author}{removed} += $removed;
            $stats{total}{by_file}{$file}{total}{added}     += $added;
            $stats{total}{by_file}{$file}{total}{removed}   += $removed;
        }
    }
    close GIT_LOG;

    if ( ! open(GIT_BLAME,'-|',"git blame -w $file") ) {
        die "Failed to process 'git blame -w $file': $!\n";
    }
    while (my $log_line = ) {
        if ( $log_line =~ m{\((.*?)\s+\d{4}} ) {
            my $author = $1;
            $stats{final}{by_author}{$author}     ++;
            $stats{final}{by_file}{$file}{$author}++;

            $stats{final}{by_author}{total}       ++;
            $stats{final}{by_file}{$file}{total}  ++;
            $stats{final}{by_file}{$file}{total}  ++;
        }
    }
    close GIT_BLAME;
}
close GIT_LS;

print "Total lines committed by author by file\n";
printf "%25s %25s %8s %8s %9s\n",'file','author','added','removed','pct add';
foreach my $file (sort keys %{$stats{total}{by_file}}) {
    printf "%25s %4.0f%%\n",$file
            ,100*$stats{total}{by_file}{$file}{total}{added}/$stats{total}{by_author}{total}{added};
    foreach my $author (sort keys %{$stats{total}{by_file}{$file}}) {
        next if $author eq 'total';
        if ( $stats{total}{by_file}{$file}{total}{added} ) {
            printf "%25s %25s %8d %8d %8.0f%%\n",'', $author,@{$stats{total}{by_file}{$file}{$author}}{qw{added removed}}
            ,100*$stats{total}{by_file}{$file}{$author}{added}/$stats{total}{by_file}{$file}{total}{added};
        } else {
            printf "%25s %25s %8d %8d\n",'', $author,@{$stats{total}{by_file}{$file}{$author}}{qw{added removed}} ;
        }
    }
}
print "\n";

print "Total lines in the final project by author by file\n";
printf "%25s %25s %8s %9s %9s\n",'file','author','final','percent', '% of all';
foreach my $file (sort keys %{$stats{final}{by_file}}) {
    printf "%25s %4.0f%%\n",$file
            ,100*$stats{final}{by_file}{$file}{total}/$stats{final}{by_author}{total};
    foreach my $author (sort keys %{$stats{final}{by_file}{$file}}) {
        next if $author eq 'total';
        printf "%25s %25s %8d %8.0f%% %8.0f%%\n",'', $author,$stats{final}{by_file}{$file}{$author}
            ,100*$stats{final}{by_file}{$file}{$author}/$stats{final}{by_file}{$file}{total}
            ,100*$stats{final}{by_file}{$file}{$author}/$stats{final}{by_author}{total}
        ;
    }
}
print "\n";


print "Total lines committed by author\n";
printf "%25s %8s %8s %9s\n",'author','added','removed','pct add';
foreach my $author (sort keys %{$stats{total}{by_author}}) {
    next if $author eq 'total';
    printf "%25s %8d %8d %8.0f%%\n",$author,@{$stats{total}{by_author}{$author}}{qw{added removed}}
        ,100*$stats{total}{by_author}{$author}{added}/$stats{total}{by_author}{total}{added};
};
print "\n";


print "Total lines in the final project by author\n";
printf "%25s %8s %9s\n",'author','final','percent';
foreach my $author (sort keys %{$stats{final}{by_author}}) {
    printf "%25s %8d %8.0f%%\n",$author,$stats{final}{by_author}{$author}
        ,100*$stats{final}{by_author}{$author}/$stats{final}{by_author}{total};
}

推荐阅读
携手相约幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有