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


458

Gitリポジトリ内の特定の作成者によって変更された行をカウントする、呼び出すことができるコマンドはありますか?Githubがインパクトグラフに対してこれを行うため、コミット数をカウントする方法が存在する必要があることを知っています。


1
Linuxカーネル開発の統計を収集する有名なツールを検討するかもしれませんgit://git.lwn.net/gitdm.git。たとえば、リポジトリはこちらです。
0andriy

回答:


310

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

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

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

スクリプトに渡す場合、 "oneline"形式を削除することも、空のログ形式で実行できます。JakubNarębskiがコメントしたように、これ--numstatも別の方法です。行ごとではなくファイルごとの統計を生成しますが、解析がさらに簡単です。

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

2
これは私が期待した方法で出力を提供し、これを達成しようとしている他の訪問者にとってより役立つので、私の受け入れられた回答を変更しました。
Gav、

14
統計情報を少し簡単に追加したい場合--numstat--shortstat、代わりに使用できます。
JakubNarębski、2009

8
そこにも「--no-merges」を追加したいかもしれません。
ヨーヨー

9
この質問については申し訳ありませんが、数字から何がわかりますか?2つの行があり、それらが何を言っているのか私にはわかりません。行が変更され、追加されましたか?
Informatic0re

2
@ Informatic0re git help logは、最初の行が追加され、2番目の行が削除されたことを示しています。
ThomasH

599

これにより、作成者に関するいくつかの統計が得られます。必要に応じて変更してください。

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でテスト済み)。スクリプトよりも直接の使用に適しています。

これのgitの-クイック統計(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

ここに画像の説明を入力してください


18
この素敵なロングライナーをありがとう!このawkのスポットは全員のデッキをスワブしました(正確、高速、余分な奇妙な出力はありません)。当然のことながら、これがawkが設計した種類のものであることを考えると...パーティーに遅すぎたのは残念です。
zxq9 2012年

4
@ zxq9:質問が出されたとき、私はスタックオーバーフローすらしていなかったので、ここでの回答に刺激を受けました。人々がこれを必要とし続けるので、私がここのみんなをゆっくり追い越してくれることを願っています
アレックス、

9
これはgawkawk
素晴らしく

1
@samthebest、ファイルの移動が適切な統計を反映していないため。行は変更されません。アレックスへ:私はGitについて話している。ところで、元の質問に対する私のコメントを見てください。
0andriy

2
URLはあなたのために動作しない場合は、これを試してください:git clone https://github.com/arzzen/git-quick-stats.git
ニコラス

226

誰かがコードベース内のすべてのユーザーの統計情報を確認したい場合に備えて、私の同僚の数人が最近この恐ろしい1行を考え出しました。

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〜15,000のコミットがあるリポをクランチするのに数分かかります。)


12
すごい!michael,: 6057 files changed, 854902 insertions(+), 26973 deletions(-), 827929 net
マイケルJ.カルキンス

1
@EugenKonkovは、挿入として定義されているコードで-削除です。
Dan

13
これは、リポジトリの合計結果を提供し、プラグインなしで実行できる唯一のコマンドです。
オメルファルクAlmalı

1
多数のユーザーが一緒にリストされています。ほぼすべての可能な開発者の組み合わせが戻ってきます。私の終わりの奇妙さ?
デイモン

2
@ BenSewards、LinuxのWindowsサブシステムを使用してWindowsでBashを使用できます。詳細はこちら
mjsr

152

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

https://github.com/casperdcl/git-fame(@fraczで言及)にもPythonバージョンがあります

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    |
+------------------------+--------+---------+-------+--------------------+

ただし、注意が必要です。Jaredがコメントで述べたように、非常に大きなリポジトリで実行するには数時間かかります。ただし、Gitデータを大量に処理する必要があることを考えると、それが改善されるかどうかはわかりません。


1
これは素晴らしいですがとても遅い
Jared Burrows 2014年

1
2015年半ばのMacbookと中規模の大規模Androidプロジェクト(127k LoC)でうまく機能しました。2〜3分。
maxweber 2015年

2
現在のユーザーの総ロケーション/コミット/ファイルの@Vincentパーセント。
Ciro Santilli郝海东冠状病六四事件法轮功

1
変更ブランチ、タイムアウト、およびフォルダを除外:git fame --branch=dev --timeout=-1 --exclude=Pods/*
jonmecer

1
@AlexanderMillsブロブの行を有意義に数えることができないためだと思います
Ciro Santilli郝海东冠状病六四事件法轮功

103

次のコードは、現在コードベースにある行が最も多いユーザーを確認するのに役立ちます。

git ls-files -z | xargs -0n1 git blame -w | ruby -n -e '$_ =~ /^.*\((.*?)\s[\d]{4}/; puts $1.strip' | sort -f | uniq -c | sort -n

他の回答は、主にコミットで変更された行に焦点を当てていますが、コミットが存続せず上書きされた場合、それらはチャーンされた可能性があります。上記の呪文では、すべてのコミッターが一度に1つだけではなく、行ごとにソートされます。git blame(-C -M)にいくつかのオプションを追加して、ファイル間のファイルの移動と行の移動を考慮したより良い数値を取得できますが、そうすると、コマンドの実行時間が大幅に長くなる可能性があります。

また、すべてのコミッターのすべてのコミットで変更された行を探している場合は、次の小さなスクリプトが役立ちます。

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


31
私は+1しようとしていましたが、解決策はルビーに依存していることに気付きました... :(
mac

3
文字列の置換にルビを使用するだけなので、ルビを使用しないように簡単に変更できます。perl、sed、pythonなどを使用できます
mmrobins

21
UTF-8での無効なバイトシーケンス(例外ArgumentError):-e:1: `<メイン> 'で私のために動作しません
のMichałDębski

1
/^.*\((.*?)\s[\d]{4}/作成/^.*?\((.*?)\s[\d]{4}/者としてソース内の括弧が一致しないようにする必要があります。
Timothy Gu

1
mmm私の実行は、悪い解析のために、存在さえしていない多くのユーザーを示しました。信頼できる答えではないと思います。
mjsr 2017年

92

特定のブランチ上の特定の作成者(またはすべての作成者)によるコミット数をカウントするには、git-shortlogを使用できます。特にgitリポジトリで実行する場合--numberedなど--summary、そのオプションを参照してください。

$ git shortlog v1.6.4 --numbered --summary
  6904  Junio C Hamano
  1320  Shawn O. Pearce
  1065  Linus Torvalds
    692  Johannes Schindelin
    443  Eric Wong

2
v1.6.4この例では、出力を確定的にするためにここにあることに注意してください。gitリポジトリからクローンやフェッチをいつ行っても同じです。
JakubNarębski2012

を含むv1.6.4fatal: ambiguous argument 'v1.6.4': unknown revision or path not in the working tree.
Vlad the Impala '29

5
ああ、いや、「gitリポジトリで実行したとき」は見逃しました。公平を期すために、ほとんどの人が文句を言わない gitのレポでこのコマンドを実行します。実際にはかなりのマージンで。
Vlad the Impala 2012

4
git shortlog -sneまたは、マージを含めない場合git shortlog -sne --no-merges
Mark Swardstrom 2013

1
@Swards:-sis --summary-nis --numbered、および[new] -e--email、著者のメールを表示することです(.mailmap修正を考慮して、同じメールの著者を異なるメールアドレスで個別にカウントします)。についての良い電話--no-merges
JakubNarębski2013

75

アレックスGerty3000を見た後の答え、私はワンライナーを短くしようとしました:

基本的に、git log numstatを使用し、ファイル数を追跡しない変更された。

Mac OSX上のGitバージョン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

カントはそれのエイリアスを作る:-(
ブラット

33

シェルワンライナーを使用したAaronMからの回答は良いですが、実際には、ユーザー名と日付の間に空白の量が異なる場合にスペースがユーザー名を破損する、さらに別のバグがあります。破損したユーザー名はユーザー数の複数の行を提供し、それらを自分で合計する必要があります。

この小さな変更で問題が解決しました:

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の後の+に注意してください。

これは、少なくとも私が件名をグーグルで回すのは2回目なので、実際に、自分自身の記憶のために他の人を助けるためにこの答えを追加します。

  • 編集2019-01-23代わりに電子メールで集約--show-emailするgit blame -wために追加されました。一部の人々はName異なるコンピューターで異なるフォーマットを使用し、時には同じ名前の2人が同じgitで作業しているためです。

perlを使用したこの回答は、ルビベースの回答よりも少しうまくいくように見えました。Rubyは実際のUTF-8テキストではない行を窒息させ、perlは文句を言わなかった。しかし、perlは正しいことをしましたか?知りません。
ステフェイン・グーリッホン

結果としてサブモジュールが生成されますunsupported file typeが、それ以外の場合でもサブモジュールは正常に動作するようです(スキップされます)。
ウラジミール・Čunát

24

以下は、すべての著者の統計を生成する短いワンライナーです。https://stackoverflow.com/a/20414465/1102119にある上記のDanのソリューションよりもはるかに高速です(鉱山はO(NM)ではなく時間の複雑さO(N)を持っています。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

4
いいですが、出力はどういう意味ですか?
ゲイリーウィロビー

追加する必要があります。追加--no-show-signatureしないと、コミットにpgp署名した人はカウントされません。
Philihpバスビー2017

2
ins [a]
-del

このコマンドをgit configに追加して、「git count-lines」で呼び出すことができるようにするにはどうすればよいですか?
takanuva15

気にしないで、私はそれを理解しました:count-lines = "!f() { 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; }; f"。(私はWindowsを使用していることに注意してください。さまざまな種類の引用符を使用する必要がある場合があります)
takanuva15

21

@mmrobins @AaronM @ErikZ @JamesMishraは、すべてに共通の問題があるバリアントを提供しました:gitに、スクリプトの消費を目的としていない情報の混合を生成するよう要求します。 。

これは、一部の行が有効なUTF-8テキストではない場合、および一部の行が正規表現に一致する場合に発生します(これはここで発生します)。

以下は、これらの問題がない変更された行です。それはgitに別々の行にきれいにデータを出力するように要求します。これにより、必要なものを確実にフィルタリングすることが容易になります:

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が大幅に高速化されます)。


素敵なラインがあり、とてもクールで、簡単に混ぜ合わせることができますが、これは元の投稿者が要求したことを実行できず、gitの作者によるカウントを提供します。もちろん、それを実行してwc-lなどを実行できますが、リポジトリ内のすべての作成者について繰り返す必要があります。
AaronM 2016

1
@AaronM私はあなたの批判を理解していません。この行AFAIKは、あなたと同じ統計を出力しますが、より堅牢です。したがって、「元の投稿者が要求したことを実行できなかった場合、gitからの作者によるカウントを提供してください」という私の答えは、さらにあなたの答えです。教えてください。
ステフェイン・グーリッホン

誤解して申し訳ありませんが、コマンドはそれぞれの著者名ごとに変更する必要があると思いました。他の文字列のgrepについてのあなたのコメントが私を導きましたが、それは私の誤解でした。
AaronM 2016

これはとても素晴らしいです。ありがとう!
Tek

16

真ん中にルビを入れて解決策が与えられましたが、デフォルトでは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

5
更新された正規表現は意味のある違いをもたらさず、最初の括弧をエスケープしなかったので壊れています。ただし、私の前のコード行で、ラッチするコード行にビットが見つかる場合があります。これはより確実に機能します:git ls-files -z | xargs -0n1 git blame -w | perl -n -e '/^.*?\((.*?)\s[\d]{4}/; print $ 1、 "\ n"' | sort -f | uniq -c | sort -n
アーロンM

より信頼できる正規表現を作ってくれてありがとう。より堅牢なバリアントのための私の答えを参照してくださいstackoverflow.com/a/36090245/1429390
ステフェイン・グーリッホン

13

加えて、チャールズ・ベイリーの答え、あなたが追加したい場合があります-Cコマンドにパラメータを。それ以外の場合、ファイルの内容が変更されていなくても、ファイル名の変更は、追加と削除の数が多い(ファイルに行が含まれている限り)と見なされます。

説明するために、ここにあるコミット使用しているとき、私のプロジェクトの1から周囲に移動されたファイルのたくさんの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(-)

私の意見では、ファイルの名前を変更することは、ファイルを最初から書き込むよりもはるかに小さい操作であるため、後者は、プロジェクトへの人の影響のより現実的なビューを提供します。


2
「git log --oneline --shortstat」を実行すると、結果が得られません。エディション数を含むコミットのリストがありますが、総数はありません。すべてのgitリポジトリで編集された行の総数を取得するにはどうすればよいですか?
Mehdi

12

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>
=====================================================

「スコア」とはどういう意味ですか?
user11171 2018

@Volte npm iはnpm installのショートカットです
Michiel

はい、承知しています。私-gは、パッケージ名の前に来る必要がありましたmacOS。単に助けようとする。
Volte

11

以下は、特定のログクエリに対するユーザーごとの影響をまとめた簡単な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

2
このスクリプトはすばらしいですが、単一行のコミットしかない著者は除外されます!修正するには、次のように変更します。changes= /(\ d +)Insertion。*(\ d +)deleted / .match(line)
Larry Gritz

9

これは最良の方法であり、すべてのユーザーによるコミットの総数を明確に示します

git shortlog -s -n

2
便利ですが、それは合計コード行数ではなくコミット数です
Diolor 2018年

5

上記の短い回答の修正を提供しましたが、私のニーズには十分ではありませんでした。コミットされた行と最終的なコードの行の両方を分類できるようにする必要がありました。また、ファイル別に分類したかった。このコードは再帰的ではなく、単一のディレクトリの結果のみを返しますが、誰かがさらに先に進みたい場合は良いスタートです。コピーしてファイルに貼り付け、実行可能にするか、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};
}

このエラーが発生します:x.pl行71でのゼロによる不正な除算
Vivek Jha

71行目で、違法な除算をゼロで対処しました。編集がない場合に発生すると考えてください。ただし、これは少し前に書いたものです。
AaronM 2015

2

Windowsユーザーの場合、指定した作成者の追加/削除された行をカウントする次のバッチスクリプトを使用できます

@echo off

set added=0
set removed=0

for /f "tokens=1-3 delims= " %%A in ('git log --pretty^=tformat: --numstat --author^=%1') do call :Count %%A %%B %%C

@echo added=%added%
@echo removed=%removed%
goto :eof

:Count
  if NOT "%1" == "-" set /a added=%added% + %1
  if NOT "%2" == "-" set /a removed=%removed% + %2
goto :eof

https://gist.github.com/zVolodymyr/62e78a744d99d414d56646a5e8a1ff4f


2

ここにあなたの人生を楽にする素晴らしいレポがあります

git-quick-stats

brewがインストールされているMacの場合

brew install git-quick-stats

走る

git-quick-stats

リストされている番号を入力してEnterキーを押すことにより、このリストから必要なオプションを選択するだけです。

 Generate:
    1) Contribution stats (by author)
    2) Contribution stats (by author) on a specific branch
    3) Git changelogs (last 10 days)
    4) Git changelogs by author
    5) My daily status
    6) Save git log output in JSON format

 List:
    7) Branch tree view (last 10)
    8) All branches (sorted by most recent commit)
    9) All contributors (sorted by name)
   10) Git commits per author
   11) Git commits per date
   12) Git commits per month
   13) Git commits per weekday
   14) Git commits per hour
   15) Git commits by author per hour

 Suggest:
   16) Code reviewers (based on git history)


1

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

1
いいえ、それはWONT!、あなたはこれを他の場所に投稿しました、それはmacsとlinuxでエラーを生成します、gitが作られたコンピューターのタイプです!
Pizzaiola Gorgonzola 2013

1

次を使用してログをファイルに保存します。

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

0

あなたはGitのせいにしたい

統計情報を表示する--show-statsオプションがあります。


私は試しましたblameが、OPが必要だと思った統計を実際に提供しませんでしたか?
CBベイリー

おかげで、これは.mailmapにも役立ちました。
Gav、

0

質問は特定の著者に関する情報を求めましたが、回答の多くは、変更されたコード行に基づいて著者のランク付けされたリストを返すソリューションでした。

これは私が探していたものでしたが、既存のソリューションは完全ではありませんでした。Googleを介してこの質問を見つける可能性のある人々のために、私はそれらにいくつかの改善を加え、それらをシェルスクリプトにして、以下に表示します。注釈付きのもの(私はこれを維持します)は私の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

0

これまでのところ私が特定した最良のツールは、ギチンスペクターです。ユーザーごと、週ごとなどのセットレポートを提供します。npmを使用して以下のようにインストールできます。

npm install -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

0

このPerlスクリプトを作成して、そのタスクを実行しました。

#!/usr/bin/env perl

use strict;
use warnings;

# save the args to pass to the git log command
my $ARGS = join(' ', @ARGV);

#get the repo slug
my $NAME = _get_repo_slug();

#get list of authors
my @authors = _get_authors();
my ($projectFiles, $projectInsertions, $projectDeletions) = (0,0,0);
#for each author
foreach my $author (@authors) {
  my $command = qq{git log $ARGS --author="$author" --oneline --shortstat --no-merges};
  my ($files, $insertions, $deletions) = (0,0,0);
  my @lines = `$command`;
  foreach my $line (@lines) {
    if ($line =~ m/^\s(\d+)\s\w+\s\w+,\s(\d+)\s\w+\([\+|\-]\),\s(\d+)\s\w+\([\+|\-]\)$|^\s(\d+)\s\w+\s\w+,\s(\d+)\s\w+\(([\+|\-])\)$/) {
      my $lineFiles = $1 ? $1 : $4;
      my $lineInsertions = (defined $6 && $6 eq '+') ? $5 : (defined $2) ? $2 : 0;
      my $lineDeletions = (defined $6 && $6 eq '-') ? $5 : (defined $3) ? $3 : 0;
      $files += $lineFiles;
      $insertions += $lineInsertions;
      $deletions += $lineDeletions;
      $projectFiles += $lineFiles;
      $projectInsertions += $lineInsertions;
      $projectDeletions += $lineDeletions;
    }
  }
  if ($files || $insertions || $deletions) {
    printf(
      "%s,%s,%s,+%s,-%s,%s\n",
      $NAME,
      $author,
      $files,
      $insertions,
      $deletions,
      $insertions - $deletions
    );
  }
}

printf(
  "%s,%s,%s,+%s,-%s,%s\n",
  $NAME,
  'PROJECT_TOTAL',
  $projectFiles,
  $projectInsertions,
  $projectDeletions,
  $projectInsertions - $projectDeletions
);

exit 0;

#get the remote.origin.url joins that last two pieces (project and repo folder)
#and removes any .git from the results. 
sub _get_repo_slug {
  my $get_remote_url = "git config --get remote.origin.url";
  my $remote_url = `$get_remote_url`;
  chomp $remote_url;

  my @parts = split('/', $remote_url);

  my $slug = join('-', @parts[-2..-1]);
  $slug =~ s/\.git//;

  return $slug;
}

sub _get_authors {
  my $git_authors = 'git shortlog -s | cut -c8-';
  my @authors = `$git_authors`;
  chomp @authors;

  return @authors;
}

名前を付けてgit-line-changes-by-authorに入れました/usr/local/bin。パスに保存されているgit line-changes-by-author --before 2018-12-31 --after 2020-01-01ため、2019年のレポートを取得するコマンドを発行できます。例として。そして、私がスペルミスをした場合、gitという名前は正しいスペルを提案します。

あなたは私のリポジトリが保存されているのであなたのそうではないかもしれないので_get_repo_slug、最後の部分だけを含むようにサブを調整したいかもしれません。remote.origin.urlproject/repo

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.