代码之家  ›  专栏  ›  技术社区  ›  knittl

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

  •  26
  • knittl  · 技术社区  · 16 年前

    git shortlog -s

    6 回复  |  直到 16 年前
        1
  •  46
  •   Sebastien Horin    10 年前

    这是一个老帖子,但如果有人还在找它:

    安装git extras

    brew install git-extras
    

    然后

    git summary --line
    

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

        2
  •  19
  •   Community Mohan Dere    8 年前

    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\)$"
    

    (注:同 commented trcarden ,一个 -x --exclude 这个选择行不通。
    git ls-files man page , git ls-files -x "*pdf" ... 未追踪 内容,如果 --others --ignored 已添加到 git ls文件

    或:

    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)}'
    

        3
  •  19
  •   alswl    7 年前

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

    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
  •  3
  •   user1074897 user1074897    14 年前

    #!/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 ":"
    
        5
  •  1
  •   Community Mohan Dere    8 年前

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

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

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

        6
  •  1
  •   pydsigner    10 年前

    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 blame_stats.py '**/*.py'

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

    等等。