我是否可以调用一个命令来计算Git存储库中特定作者更改的行数?我知道一定有方法来计算提交的数量,因为Github为他们的影响图这样做。


当前回答

使用以下方法将日志保存到文件:

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

其他回答

要统计给定作者(或所有作者)在给定分支上提交的数量,可以使用git-shortlog;特别是它的——编号和——摘要选项,例如在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 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 }' -

使用count-lines git-alias:

简单地创建计数行别名(每个系统一次),像这样:

git config --global alias.count-lines "! git log --author=\"\$1\" --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 }' #"

以后再用,比如:

git count-lines email@example.com

对于Windows,将Git-Bash添加到PATH(环境变量)后生效。 对于Linux,可能用gawk替换awk部分。 对于MacOS,无需任何更改即可正常工作。

使用现有脚本(更新2017)

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

它是git-quick-stats (github链接)。

复制git-quick-stats到一个文件夹,并将该文件夹添加到path。

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

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后面的+,它将占用从名称到日期的所有空白。

实际上,添加这个答案既是为了帮助别人,也是为了我自己的记忆,因为这至少是我第二次谷歌这个主题:)

增加了——show-email to git blame -w来聚合email,因为有些人在不同的计算机上使用不同的Name格式,有时两个同名的人在同一个git中工作。

下面是一个快速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

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

这正是我想要的,但现有的解决方案并不完美。为了方便人们通过谷歌找到这个问题,我对它们进行了一些改进,并将其制成一个shell脚本,下面显示该脚本。

它不依赖于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