如何计算总线路由特定作者在一个Git仓库改变了吗?(How to count total lines

2019-06-18 09:03发布

是否有一个命令,我可以调用这会对由特定作者在一个Git仓库改线? 我知道一定有方法来计算提交的数目为Github上做这行的影响图。

Answer 1:

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

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

这给出了对当前HEAD所有提交的统计数据。 如果你想在其他分支机构加起来统计你将不得不向他们提供作为参数传递给git log

对于传递给一个脚本,删除连“ONELINE”格式可以用空的日志格式来完成,并经的JakubNarębski评论--numstat是另一种选择。 它会生成每个文件,而不是每行的统计数据,但更容易解析。

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


Answer 2:

这使得关于作者,修改所需的一些统计数据。

使用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上测试)一个新的包。 它更适合直接使用,而不是脚本。

这是混帐快速统计(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



Answer 3:

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

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



Answer 4:

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

还有Python版本在https://github.com/casperdcl/git-fame (由@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    |
+------------------------+--------+---------+-------+--------------------+

但要注意:由贾里德注释中,做一个非常大的库需要几个小时。 不知道是否可能被提高,虽然考虑到它必须处理这么多的Git数据。



Answer 5:

我发现下面是有用的,看看谁曾认为是当前代码库中最行:

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的怪(-C-M),以获得一些更好的数字,采取文件之间的文件移动和线运动考虑在内,但如果你做的命令可能会遇到很多时间。

另外,如果你正在寻找线在所有的开发者都提交变化,遵循小脚本是有帮助的:

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



Answer 6:

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


Answer 7:

看着Alex的Gerty3000的回答后,我试图缩短一行程序:

基本上,使用Git日志numstat,而不是保存文件数量的轨迹变化。

Git的在Mac OSX版本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


Answer 8:

在回答来自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这将消耗掉所有的空格,从名字到日后注意+。

其实加入这个答案不仅是为了我自己rememberance作为帮助别人,因为这至少是我第二次谷歌的主题:)

  • 编辑2019年1月23日增加了--show-emailgit blame -w对电子邮件聚集而是因为一些人使用不同的Name在不同的计算机格式,有时两个人具有相同名称在同一git的正常工作。


Answer 9:

@mmrobins @AaronM @ErikZ @JamesMishra提供的变种,都有一个共同的问题:他们问git的产生并非用于脚本消费,包括在同一行库行内容信息的混合物,然后用正则表达式匹配的混乱。

这是一个问题,当一些线不合法的UTF-8文本,以及当一些线正好匹配的正则表达式(这发生在这里)。

下面是修改线不存在这些问题。 它要求混帐干净输出数据在不同的行,这使得它易于过滤我们想要稳健:

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)。



Answer 10:

下面是一个简短的一行,对所有作者产生的统计数据。 它比上面丹的解决方案快得多在https://stackoverflow.com/a/20414465/1102119 (我有时间复杂度为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


Answer 11:

在中间红宝石的溶液给出的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


Answer 12:

除了查尔斯·贝利的回答 ,您可能要到加-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(-)

在我看来,后者给出了一个人多大的影响对项目,因为重命名文件比从头开始编写文件小得多的操作更现实的看法。



Answer 13:

下面是网住了每个用户对一个给定的日志查询的影响快速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


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


Answer 15:

这是最好的方式,它也被所有的用户给你的提交总数的清晰图像

git shortlog -s -n


Answer 16:

我上面提供一个简单的答案的修改,但我需要足够的wasnt。 我需要能够在最后的代码进行分类都致力于线路和线路。 我也想休息一下下降了文件。 此代码不递归,它只会返回的结果为一个目录,但它是一个良好的开端,如果有人想走得更远。 复制并粘贴到一个文件,并执行或用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};
}


Answer 17:

这里这个脚本会做到这一点。 把它放进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 ":"


Answer 18:

保存您登录到使用文件:

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


Answer 19:

你想Git的指责 。

有一个 - 显示,统计数据选项,打印一些,那么,统计数据。



Answer 20:

这个问题要求对特定作者的信息,但很多问题的答案都是一个返回排名根据他们的行代码作者的名单变化的解决方案。

这正是我一直在寻找,但现有的解决方案并不相当完美。 在可以找到通过谷歌这个问题的人的利益,我做了对他们的一些改进,使他们成为一个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


Answer 21:

最好的工具,到目前为止,我identfied是gitinspector。 它给每个用户设定的报告,每周等您可以安装像下面NPM

NPM安装-g gitinspector

这些链接以获得更多详情

https://www.npmjs.com/package/gitinspector

https://github.com/ejwa/gitinspector/wiki/Documentation

https://github.com/ejwa/gitinspector

示例命令是

gitinspector -lmrTw 
gitinspector --since=1-1-2017 etc


文章来源: How to count total lines changed by a specific author in a Git repository?