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


457

我是否可以调用一个命令来计算Git信息库中特定作者更改的行数?我知道,必须有一些方法可以计算提交次数,因为Github会对影响图进行计数。


1
您可能会考虑收集Linux内核开发统计信息的著名工具,例如Repository在这里git://git.lwn.net/gitdm.git
2015年

Answers:


310

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

git log --author="<authorname>" --oneline --shortstat

这给出了当前HEAD上所有提交的统计信息。如果您想在其他分支中添加统计信息,则必须将其作为参数提供给git log

为了传递给脚本,甚至可以使用空的日志格式删除“ oneline”格式,正如JakubNarębski所评论的那样,这--numstat是另一种选择。它生成每个文件而不是每个行的统计信息,但更易于解析。

git log --author="<authorname>" --pretty=tformat: --numstat

2
更改了我接受的答案,因为这样可以按预期方式提供输出,并且对希望实现此目标的其他访问者会更有帮助。
Gav

14
如果要累加统计信息,可以使用--numstat代替--shortstat
2009年

8
可能也想在其中添加“ --no-merger”。
yoyo

9
对此问题感到抱歉,但是数字告诉我什么?有两行,我不知道他们在告诉我什么。线路是否已添加?
Informatic0re

2
@ Informatic0re git help log告诉我,第一行是添加的行,第二行是删除的。
ThomasH '16

599

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

使用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

在此处输入图片说明


18
感谢这个可爱的长衬套!这个awk点抹了所有人的视线(准确,快速,没有额外的怪异输出)。不足为奇,考虑到这是awk设计的目的……太糟糕了,您参加聚会太晚了。
zxq9 2012年

4
@ zxq9:当我问这个问题时,我什至没有在stackoverflow上,这里的答案也启发了我。希望我会慢慢地赶上这里的每个人,因为人们不断需要它。
亚历克斯(Alex)

9
这很棒,但是我不得不改变 gawk才能awk使其在OSX终端中正常工作
Zach Lysobey 2013年

1
@samthebest,因为移动文件未反映正确的统计信息。线没有改变。致亚历克斯:我说的是Git。顺便说一句,请参阅我对原始问题的评论。
0andriy

2
如果该网址不适合您,请尝试以下操作:git clone https://github.com/arzzen/git-quick-stats.git
Nicolas

226

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

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次提交。)


12
棒极了!michael,: 6057 files changed, 854902 insertions(+), 26973 deletions(-), 827929 net
Michael J. Calkins 2013年

1
@EugenKonkov在代码中被定义为插入-删除。
2015年

13
这是唯一可提供存储库总结果且无需任何插件即可运行的命令。
奥马尔法鲁克Almalı

1
我聚集了很多用户,几乎所有可能的开发人员组合都回来了。我这怪异吗?
达蒙

2
@BenSewards,您可以使用Windows子系统(适用于Linux)在Windows上使用Bash,此处
mjsr

152

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数据,因此不确定是否可以改进。


1
这太棒了,但是太慢了
Jared Burrows 2014年

1
在2015年中期的MacBook和中型大型Android项目(127k LoC'is)上运行良好。几分钟
maxweber 2015年

2
当前用户占总位置/提交/文件的@Vincent百分比。
Ciro Santilli郝海东冠状病六四事件法轮功2015年

1
更改分支,超时并排除文件夹:git fame --branch=dev --timeout=-1 --exclude=Pods/*
jonmecer

1
@AlexanderMills我猜是因为您无法有效地计算斑点上的线条
Ciro Santilli郝海东冠状病六四事件法轮功

103

我发现以下内容对于查看谁拥有当前代码库中最多的行很有用:

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


31
我本来打算给+1,但后来我意识到解决方案取决于ruby ... :(
mac

3
您可以修改它,以免轻易使用ruby,因为我只是使用ruby进行字符串替换。您可以使用perl,sed,python等
mmrobins 2012年

21
不为我工作:-e:1:在`<主>':在UTF-8(引发ArgumentError)无效的字节序列
米哈尔Dębski

1
/^.*\((.*?)\s[\d]{4}/应该是/^.*?\((.*?)\s[\d]{4}/为了防止括号中的作者与作者匹配。
蒂莫西·古

1
嗯,由于解析错误,我的执行情况显示很多甚至不存在的用户。我认为这不是一个可靠的答案。
mjsr

92

要计算给定作者(或所有作者)在给定分支上的提交次数,可以使用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

2
请注意,v1.6.4在此示例中是为了使输出具有确定性:无论何时从git存储库克隆和/或提取,它都是相同的。
JakubNarębski2012年

包括v1.6.4给我:fatal: ambiguous argument 'v1.6.4': unknown revision or path not in the working tree.
弗拉德·黑斑羚

5
啊,不,我错过了“在git仓库上运行时”。公平地说,大多数人不会在git repo上运行此命令。实际上,确实有很大的差距。
弗拉德黑斑羚

4
git shortlog -sne或者,如果你宁愿不包括合并git shortlog -sne --no-merges
马克Swardstrom

1
@Swards:-s--summary-n--numbered,和[新] -e--email显示作者的电子邮件(并分别统计不同的电子邮件地址,同一作者,考虑到.mailmap修正)。好电话--no-merges
JakubNarębski2013年

75

在查看了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

不能给它起别名:-(
小子

33

回答来自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

注意\ s之后的+,它将占用从名称到日期的所有空格。

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

  • 编辑2019年1月23日添加--show-emailgit blame -w汇总在电子邮件上,因为有些人Name在不同的计算机上使用不同的格式,有时两个同名的人在同一个git中工作。

使用perl的答案似乎比基于红宝石的答案要好一些。Ruby在不是实际UTF-8文本的行上cho住了,perl没有抱怨。但是perl做正确的事吗?我不知道。
斯特凡纳·古里科

产生子模块,unsupported file type但是即使子模块也可以正常工作(它会跳过它们)。
弗拉基米尔·Čunát17年

24

这是一个简短的单行代码,可为所有作者提供统计数据。它比上面https://stackoverflow.com/a/20414465/1102119上 Dan的解决方案要快得多(mine具有时间复杂度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

4
很好,但是输出是什么意思?
加里·威洛比

您应该添加--no-show-signature,否则用pgp签名提交的人员将不会被计数。
Philihp Busby

2
ins [a]-del [a],ins [a],del [a],a,所以如果我是正确的插入,删除,插入,删除,名称
MrKekson

如何将这个命令添加到我的git配置中,以便可以使用“ git count-lines”来调用它?
takanuva15年

没关系,我知道了:count-lines = "!f() { 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; }; f"。(请注意,我在Windows上;您可能需要使用不同种类的引号)
takanuva15 '18

21

@mmrobins @AaronM @ErikZ @JamesMishra提供了所有共同点有问题的变体:他们要求git产生不用于脚本使用的信息混合,包括同一行中来自存储库的行内容,然后将其与正则表达式匹配。

当某些行不是有效的UTF-8文本时,以及当某些行恰巧与regexp匹配时(在这里发生),这就是一个问题。

这是一条没有这些问题的经修改的生产线。它要求git在单独的行上干净地输出数据,这使得轻松过滤我们想要的内容变得容易:

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

您可以grep输入其他字符串,例如作者邮件,提交者等。

也许首先export LC_ALL=C(假设bash)强制执行字节级处理(这也恰好从基于UTF-8的语言环境极大地提高了grep的速度)。


那里的台词很酷,很酷,您可以轻松地将其混合在一起,但是这并不能满足原始发帖人的要求,请提供来自git的作者统计。当然,您可以运行它并执行wc-l等操作,但是随后您需要为存储库中的每个作者重复一次。
AaronM '16

1
@AaronM我不理解您的批评。此行AFAIK输出与您相同的统计信息,但功能更强大。因此,如果我的回答是“无法按照原始发帖人的要求做,请从git中提供作者的计数”,那么您的答案就更多了。请赐教。
斯特凡纳·古里科

抱歉,我读错了,我认为必须为每个不同的作者姓名修改命令。您对其他字符串的grep的评论将我带到了那里,但这是我的误解。
AaronM '16

太棒了 谢谢!
Tek

16

中间给出了一个使用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

5
更新的regex不会产生有意义的变化,并且由于您没有逃脱第一个括号而被破坏了。但是,在某些情况下,我的前一个代码可能会在代码行中找到一些要锁定的位。这将更可靠地工作:git ls-files -z | xargs -0n1 git怪-w | perl -n -e'/^.*?\((.*?)\s[\d]{4}/;打印$ 1,“ \ n”'| sort -f | uniq -c | sort -n
AaronM

感谢您尝试制作更可靠的正则表达式。看我为一个更强大的变种答案stackoverflow.com/a/36090245/1429390
斯特凡纳·古里科

13

除了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(-)

在我看来,后者可以更实际地反映一个人对项目的影响,因为重命名文件比从头开始写文件要小得多。


2
当我执行“ git log --oneline --shortstat”时,我没有得到您的结果。我有一个提交列表,其中包含版本数,但没有总数。我如何获得所有git存储库中编辑的行总数?
Mehdi 2014年

12

您可以使用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 <someguy@tensorflow.org>
 585    | somelady <somelady@tensorflow.org>
 212    | niceguy <nice@google.com>
 173    | coolguy <coolgay@google.com>
=====================================================

“分数”是什么意思?
user11171

@Volte npm i只是npm安装的快捷方式
Michiel

是的,我知道。我-g必须在软件包名称之前输入macOS。只是想帮助。
Volte

11

这是一个快速的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

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

8

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

git shortlog -s -n

2
有用,但这只是提交的次数而不是总的代码行
Diolor

5

我在上面提供了一个简短答案的修改,但这不足以满足我的需求。我需要能够对提交的行和最终代码中的行进行分类。我也想按档案细分。这段代码不会递归,只会返回单个目录的结果,但是如果有人想走得更远的话,这是一个好的开始。复制并粘贴到文件中,使其成为可执行文件,或使用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 = <GIT_LS>) {
    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 = <GIT_LOG>) {
        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 = <GIT_BLAME>) {
        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};
}

我收到此错误:x.pl第71行被零除。–
Vivek Jha

在第71行中将非法除以零除以。认为没有任何编辑就会发生,但是不久前我写了这个。
亚伦

2

对于Windows用户,您可以使用以下批处理脚本,该脚本计算指定作者的添加/删除行

@echo off

set added=0
set removed=0

for /f "tokens=1-3 delims= " %%A in ('git log --pretty^=tformat: --numstat --author^=%1') do call :Count %%A %%B %%C

@echo added=%added%
@echo removed=%removed%
goto :eof

:Count
  if NOT "%1" == "-" set /a added=%added% + %1
  if NOT "%2" == "-" set /a removed=%removed% + %2
goto :eof

https://gist.github.com/zVolodymyr/62e78a744d99d414d56646a5e8a1ff4f


2

这是一个很棒的仓库,使您的生活更轻松

git-quick-stats

在安装了brew的Mac上

brew install git-quick-stats

git-quick-stats

只需输入列出的数字并按Enter键,即可从此列表中选择所需的选项。

 Generate:
    1) Contribution stats (by author)
    2) Contribution stats (by author) on a specific branch
    3) Git changelogs (last 10 days)
    4) Git changelogs by author
    5) My daily status
    6) Save git log output in JSON format

 List:
    7) Branch tree view (last 10)
    8) All branches (sorted by most recent commit)
    9) All contributors (sorted by name)
   10) Git commits per author
   11) Git commits per date
   12) Git commits per month
   13) Git commits per weekday
   14) Git commits per hour
   15) Git commits by author per hour

 Suggest:
   16) Code reviewers (based on git history)


1

此脚本将在此处完成。将其放到authorship.sh中,用chmod + x设置,一切就绪。

#!/bin/sh
declare -A map
while read line; do
    if grep "^[a-zA-Z]" <<< "$line" > /dev/null; then
        current="$line"
        if [ -z "${map[$current]}" ]; then 
            map[$current]=0
        fi
    elif grep "^[0-9]" <<<"$line" >/dev/null; then
        for i in $(cut -f 1,2 <<< "$line"); do
            map[$current]=$((map[$current] + $i))
        done
    fi
done <<< "$(git log --numstat --pretty="%aN")"

for i in "${!map[@]}"; do
    echo -e "$i:${map[$i]}"
done | sort -nr -t ":" -k 2 | column -t -s ":"

1
不,它是WONT!,您在其他地方发布了此信息,它在Mac和Linux上生成错误,您知道git制作的计算机类型是!
Pizzaiola Gorgonzola

1

使用以下命令将日志保存到文件中:

git log --author="<authorname>" --oneline --shortstat > logs.txt

对于Python爱好者:

with open(r".\logs.txt", "r", encoding="utf8") as f:
    files = insertions = deletions = 0
    for line in f:
        if ' changed' in line:
            line = line.strip()
            spl = line.split(', ')
            if len(spl) > 0:
                files += int(spl[0].split(' ')[0])
            if len(spl) > 1:
                insertions += int(spl[1].split(' ')[0])
            if len(spl) > 2:
                deletions += int(spl[2].split(' ')[0])

    print(str(files).ljust(10) + ' files changed')
    print(str(insertions).ljust(10) + ' insertions')
    print(str(deletions).ljust(10) + ' deletions')

您的输出如下所示:

225        files changed
6751       insertions
1379       deletions

0

你要怪吉特

有一个--show-stats选项可以打印一些统计信息。


我尝试过blame,但是并没有真正提供OP所需的统计信息?
CB Bailey

谢谢,这也帮助我使用.mailmap!
Gav

0

该问题要求提供有关特定作者的信息,但是许多答案都是根据他们的代码行更改返回排名的作者列表的解决方案。

这是我一直在寻找的,但是现有的解决方案并不十分完美。为了使可能会通过Google找到此问题的人们感兴趣,我对它们进行了一些改进,并将其制成了一个Shell脚本,下面显示。在我的Github上可以找到带注释的(我将继续维护)。

Perl或Ruby 都没有依赖性。此外,在行更改计数中考虑空格,重命名和行移动。只需将其放入文件中,然后将Git存储库作为第一个参数传递即可。

#!/bin/bash
git --git-dir="$1/.git" log > /dev/null 2> /dev/null
if [ $? -eq 128 ]
then
    echo "Not a git repository!"
    exit 128
else
    echo -e "Lines  | Name\nChanged|"
    git --work-tree="$1" --git-dir="$1/.git" ls-files -z |\
    xargs -0n1 git --work-tree="$1" --git-dir="$1/.git" blame -C -M  -w |\
    cut -d'(' -f2 |\
    cut -d2 -f1 |\
    sed -e "s/ \{1,\}$//" |\
    sort |\
    uniq -c |\
    sort -nr
fi


0

我写了这个Perl脚本来完成该任务。

#!/usr/bin/env perl

use strict;
use warnings;

# save the args to pass to the git log command
my $ARGS = join(' ', @ARGV);

#get the repo slug
my $NAME = _get_repo_slug();

#get list of authors
my @authors = _get_authors();
my ($projectFiles, $projectInsertions, $projectDeletions) = (0,0,0);
#for each author
foreach my $author (@authors) {
  my $command = qq{git log $ARGS --author="$author" --oneline --shortstat --no-merges};
  my ($files, $insertions, $deletions) = (0,0,0);
  my @lines = `$command`;
  foreach my $line (@lines) {
    if ($line =~ m/^\s(\d+)\s\w+\s\w+,\s(\d+)\s\w+\([\+|\-]\),\s(\d+)\s\w+\([\+|\-]\)$|^\s(\d+)\s\w+\s\w+,\s(\d+)\s\w+\(([\+|\-])\)$/) {
      my $lineFiles = $1 ? $1 : $4;
      my $lineInsertions = (defined $6 && $6 eq '+') ? $5 : (defined $2) ? $2 : 0;
      my $lineDeletions = (defined $6 && $6 eq '-') ? $5 : (defined $3) ? $3 : 0;
      $files += $lineFiles;
      $insertions += $lineInsertions;
      $deletions += $lineDeletions;
      $projectFiles += $lineFiles;
      $projectInsertions += $lineInsertions;
      $projectDeletions += $lineDeletions;
    }
  }
  if ($files || $insertions || $deletions) {
    printf(
      "%s,%s,%s,+%s,-%s,%s\n",
      $NAME,
      $author,
      $files,
      $insertions,
      $deletions,
      $insertions - $deletions
    );
  }
}

printf(
  "%s,%s,%s,+%s,-%s,%s\n",
  $NAME,
  'PROJECT_TOTAL',
  $projectFiles,
  $projectInsertions,
  $projectDeletions,
  $projectInsertions - $projectDeletions
);

exit 0;

#get the remote.origin.url joins that last two pieces (project and repo folder)
#and removes any .git from the results. 
sub _get_repo_slug {
  my $get_remote_url = "git config --get remote.origin.url";
  my $remote_url = `$get_remote_url`;
  chomp $remote_url;

  my @parts = split('/', $remote_url);

  my $slug = join('-', @parts[-2..-1]);
  $slug =~ s/\.git//;

  return $slug;
}

sub _get_authors {
  my $git_authors = 'git shortlog -s | cut -c8-';
  my @authors = `$git_authors`;
  chomp @authors;

  return @authors;
}

我把它命名git-line-changes-by-author并放入/usr/local/bin。因为它保存在我的路径中,所以我可以发出命令git line-changes-by-author --before 2018-12-31 --after 2020-01-01以获取2019年的报告。举个例子。如果我拼错了名字,git会建议正确的拼写。

您可能需要调整_get_repo_slug子项,使其仅包含的最后一部分,remote.origin.url因为我的存储库已另存为,project/repo而您可能没有。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.