web-dev-qa-db-ja.com

gitで著者ごとに変更された行の数を表示する

削除された/追加された行の数を、作成者ごとにgit履歴の特定のブランチについてグループ化したいのですが。有る git shortlog -sこれは、著者ごとのコミット数を示しています。全体的なdiffstatを取得するのに似たものはありますか?

30
knittl

それは古い投稿ですが、誰かがまだそれを探しているなら:

git extrasをインストールする

brew install git-extras

その後

git summary --line

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

38
Sebastien Horin

the SO質問「Gitリポジトリ内の特定の作成者によって変更された合計行数をカウントする方法は?」 は完全に満足できるものではないため、 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 の場合、_-x_または_--exclude_オプションは機能しません。
From _git ls-files_ man page 、_git ls-files -x "*pdf" ..._は除外されますntracked content、if _--others_または_--ignored_が_git ls-files_コマンドに追加されました。)

または:

_git ls-files "*.py" "*.html" "*.css" 
_

特定のファイルタイプのみを含める。


それでも、 "_git log_"ベースのソリューション は、次のように優れているはずです。

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

しかし、これも1つのパス(ここでは2つのコミット)に対するものであり、ブランチごとのすべてのブランチに対するものではありません。

18
VonC

1行のコード(サポート時間範囲の選択):

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
8
alswl

このスクリプトは、ここで行います。それを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 ":"
2
user1074897

From Gitリポジトリ内の特定の作成者によって変更された総行数をカウントする方法

次のコマンドの出力は、合計を合計するためにスクリプトに送信するのがかなり簡単なはずです。

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

これにより、現在のHEADでのすべてのコミットの統計が得られます。他のブランチの統計を合計したい場合は、それらをgit logの引数として指定する必要があります。

2
Nicolas

私のリポジトリでは、浮かぶ1ライナーから大量のゴミ出力を受け取ったので、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'

1つのサブディレクトリにあるファイルのみを表示する場合:blame_stats.py some_dir

等々。

1
pydsigner