在 git 中显示每个作者的更改行数

Posted

技术标签:

【中文标题】在 git 中显示每个作者的更改行数【英文标题】:Show number of changed lines per author in git 【发布时间】:2011-02-16 18:03:18 【问题描述】:

我想查看删除/添加的行数,按作者为 git 历史中的给定分支分组。 git shortlog -s 向我显示了每个作者的提交次数。有什么类似的东西可以得到一个整体的 diffstat 吗?

【问题讨论】:

***.com/questions/1265040/… 有帮助吗?如git shortlog abranch --numbered --summary @VonC, i git shortlog --numbered --summarygit shortlog -s -n一样,只会显示提交次数,不会显示修改的行数 我使用 'git shortlog -sn' 而不是 'git shortlog -s' --- 它允许我按数量对作者进行排序 【参考方案1】:

这是一个旧帖子,但如果有人仍在寻找它:

安装 git extras

brew install git-extras

然后

git summary --line

https://github.com/tj/git-extras

【讨论】:

apt-get install git-extras 适用于 Linux 用户 fatal: unrecognized argument: --line 我认为他们在最新版本中删除了该选项 @M2X,看起来 git line-summary 有效,尽管在文档中说,它已弃用 --line github.com/tj/git-extras/blob/master/… 我喜欢这个工具的输出。不错。 @alex 你为那些分布使用 apt 来管理数据包的人... :)【参考方案2】:

一行代码(支持时间范围选择):

git log --since=4.weeks --numstat --pretty="%ae %H" | sed 's/@.*//g' | awk ' if (NF == 1) name = $1; if(NF == 3) plus[name] += $1; minus[name] += $2 END  for (name in plus) print name": +"plus[name]" -"minus[name]' | sort -k2 -gr

解释:

git log --since=4.weeks --numstat --pretty="%ae %H" \
    | sed 's/@.*//g'  \
    | awk ' if (NF == 1) name = $1; if(NF == 3) plus[name] += $1; minus[name] += $2 END  for (name in plus) print name": +"plus[name]" -"minus[name]' \
    | sort -k2 -gr

# query log by time range
# get author email prefix
# count plus / minus lines
# sort result

输出:

user-a: +5455 -3471
user-b: +5118 -1934

【讨论】:

在回购的整个生命周期中,每次我需要问这个问题时,我都会访问这个答案;我所做的就是将 4.weeks 更改为 10.years【参考方案3】:

由于the SO question "How to count total lines changed by a specific author in a Git repository?" 并不完全令人满意,commandlinefu 有替代方案(尽管不是每个分支):

git ls-files | while read i; do git blame $i | sed -e 's/^[^(]*(//' -e 's/^\([^[:digit:]]*\)[[:space:]]\+[[:digit:]].*/\1/'; done | sort | uniq -ic | sort -nr

它包含二进制文件,这不好,所以你可以(删除真正随机的二进制文件):

git ls-files | grep -v "\.\(pdf\|psd\|tif\)$"

(注意:trcarden 的 commented,-x--exclude 选项不起作用。 从 git ls-files man page 开始,git ls-files -x "*pdf" ... 只会排除 未跟踪 的内容,如果 --others--ignored 被添加到 git ls-files 命令。)

或者:

git ls-files "*.py" "*.html" "*.css" 

只包含特定的文件类型。


不过,"git log"-based solution 应该更好,例如:

git log --numstat --pretty="%H" --author="Your Name" commit1..commit2 | awk 'NF==3 plus+=$1; minus+=$2 END printf("+%d, -%d\n", plus, minus)'

但同样,这是针对一条路径(此处为 2 次提交),而不是针对每个分支的所有分支。

【讨论】:

git log 是唯一不适合我的东西,好建议! 您实际上不能通过指定的方法忽略二进制文件。 ls-files 上的 -x 命令仅适用于“未跟踪文件”常见错误。 @trcarden 很好。我已经编辑了答案并提出了另一种排除二进制文件的方法。【参考方案4】:

这里的脚本会做到这一点。将其放入 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 ":"

【讨论】:

在 Mac OS X 10.6.8 和 Debian Linux 5.0.8 上获得这个:/Users/slippyd/Desktop/git-authorship: line 3: declare: -A: invalid option declare: usage: declare [-afFirtx] [-p] [name[=value] ...] 在 mac 上遇到与 slipp 相同的错误,我将 -A 更改为 -a (如错误消息中所指定),但脚本仍然失败,显然它不处理名称中的空格(就像名字和姓氏之间的空格),仍在寻找可行的解决方案,您可能认为这是许多人需要的东西,以获得晋升:),显然不是。好吧,我只会说 90% 的老板! 如果它抱怨声明错误,请使用 #!/bin/bash 而不是 #!/bin/sh @DonatasOlsevičius bash 在 mac 上仍然没有帮助,而且我遇到了与 Pizzaiola 相同的问题,我认为,空间相关错误 我不知道mac有什么问题。也许没有 bash 而是使用不同的 shell?【参考方案5】:

在我的存储库中,我从漂浮的单线中得到了很多垃圾输出,所以这里有一个 Python 脚本来做正确的事情:

import subprocess
import collections
import sys


def get_lines_from_call(command):
    return subprocess.check_output(command).splitlines()

def get_files(paths=()):
    command = ['git', 'ls-files']
    command.extend(paths)
    return get_lines_from_call(command)

def get_blame(path):
    return get_lines_from_call(['git', 'blame', path])


def extract_name(line):
    """
    Extract the author from a line of a standard git blame
    """
    return line.split('(', 1)[1].split(')', 1)[0].rsplit(None, 4)[0]


def get_file_authors(path):
    return [extract_name(line) for line in get_blame(path)]


def blame_stats(paths=()):
    counter = collections.Counter()
    for filename in get_files(paths):
        counter.update(get_file_authors(filename))
    return counter


def main():
    counter = blame_stats(sys.argv[1:])
    max_width = len(str(counter.most_common(1)[0][1]))
    for name, count in reversed(counter.most_common()):
        print('%s %s' % (str(count).rjust(max_width), name))

if __name__ == '__main__':
    main()

请注意,脚本的参数将传递给git ls-files,因此如果您只想显示 Python 文件: blame_stats.py '**/*.py'

如果您只想显示一个子目录中的文件:blame_stats.py some_dir

等等。

【讨论】:

【参考方案6】:

来自How to count total lines changed by a specific author in a Git repository?

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

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

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

【讨论】:

以上是关于在 git 中显示每个作者的更改行数的主要内容,如果未能解决你的问题,请参考以下文章

单词统计:对程序设计语言源文件统计字符数单词数行数,统计结果以指定格式输出到默认文件中

作业-- 统计文本文件中的字符数单词数行数

python脚本: 双向统计文件字符单词数行数

更漂亮:仅针对文件的更改行运行

Android 简单统计文本文件字符数单词数行数Demo

如何计算作者在 git 中两个版本之间更改的行数?