Bagaimana cara menghitung total baris yang diubah oleh penulis tertentu dalam repositori Git?


458

Apakah ada perintah yang bisa saya panggil yang akan menghitung baris yang diubah oleh penulis tertentu dalam repositori Git? Saya tahu bahwa harus ada cara untuk menghitung jumlah komit karena Github melakukan ini untuk grafik Dampak mereka.


1
Anda dapat mempertimbangkan alat terkenal yang mengumpulkan statistik untuk pengembangan kernel Linux, misalnya, Repositori ada di sini git://git.lwn.net/gitdm.git.
0andriy

Jawaban:


310

Output dari perintah berikut seharusnya cukup mudah untuk dikirim ke skrip untuk menjumlahkan totalnya:

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

Ini memberikan statistik untuk semua komitmen pada KEPALA saat ini. Jika Anda ingin menambahkan statistik di cabang lain, Anda harus menyediakannya sebagai argumen git log.

Untuk meneruskan ke skrip, menghapus bahkan format "oneline" dapat dilakukan dengan format log kosong, dan seperti dikomentari oleh Jakub Narębski, --numstatadalah alternatif lain. Ini menghasilkan per-file daripada statistik per-baris tetapi bahkan lebih mudah untuk diuraikan.

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

2
Mengubah jawaban yang saya terima karena ini memberikan hasil seperti yang saya harapkan, dan akan lebih bermanfaat bagi pengunjung lain yang ingin mencapai ini.
Gav

14
Anda bisa menggunakan --numstatalih-alih --shortstatjika Anda ingin menambahkan statistik sedikit lebih mudah.
Jakub Narębski

8
Mungkin ingin menambahkan "--tidak ada penggabungan" di sana juga.
yoyo

9
maaf untuk pertanyaan ini, tetapi nomor berapa yang memberi tahu saya? Ada dua baris dan saya tidak tahu apa yang mereka katakan kepada saya. Garis diangkat dan ditambahkan?
Informatic0re

2
@ Informatic0re git help logmemberi tahu saya bahwa baris pertama ditambahkan, baris kedua dihapus.
ThomasH

599

Ini memberikan beberapa statistik tentang penulis, modifikasi sesuai kebutuhan.

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

Menggunakan Awk di Mac OSX:

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

EDIT (2017)

Ada paket baru di github yang terlihat apik dan menggunakan bash sebagai dependensinya (diuji di linux). Ini lebih cocok untuk penggunaan langsung daripada skrip.

Nya git-quick-stats (tautan github) .

Salin git-quick-statske folder dan tambahkan folder ke jalur.

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

Pemakaian:

git-quick-stats

masukkan deskripsi gambar di sini


18
Terima kasih untuk kalimat panjang yang indah ini! Tempat awk ini mengusap dek semua orang (akurat, cepat, tidak ada output aneh). Tidak mengherankan, mengingat ini adalah jenis hal yang dirancang untuk awk ... Sayang sekali Anda begitu terlambat ke pesta.
zxq9

4
@ zxq9: Saya bahkan tidak berada di stackoverflow ketika pertanyaan diajukan dan saya terinspirasi oleh jawaban di sini. semoga saja saya perlahan-lahan menyusul semua orang di sini karena orang-orang tetap membutuhkan ini.
Alex

9
Ini bekerja mengagumkan, tapi saya harus mengubah gawkuntuk awkuntuk membuatnya bekerja di terminal OSX
Zach Lysobey

1
@samthebest, karena memindahkan file tidak mencerminkan statistik yang tepat. Garis tidak berubah. Untuk Alex: Saya sedang berbicara tentang Git. Btw, lihat komentar saya untuk pertanyaan asli.
0andriy

2
Jika url tidak berfungsi untuk Anda, coba ini:git clone https://github.com/arzzen/git-quick-stats.git
Nicolas

226

Jika ada yang ingin melihat statistik untuk setiap pengguna dalam basis kode mereka, beberapa rekan kerja saya baru-baru ini membuat satu kalimat yang mengerikan ini:

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";}'

(Butuh beberapa menit untuk membaca repo kami, yang memiliki komitmen sekitar 10-15rb.)


12
Itu luar biasa! michael,: 6057 files changed, 854902 insertions(+), 26973 deletions(-), 827929 net
Michael J. Calkins

1
@EugenKonkov dalam kode yang didefinisikan sebagai penyisipan - penghapusan.
Dan

13
itulah satu-satunya perintah yang memberikan hasil total untuk repositori dan berjalan tanpa plugin apa pun.
Ömer Faruk Almali

1
Saya mendapatkan banyak pengguna terdaftar bersama, hampir setiap kemungkinan kombinasi pengembang kembali. keanehan di ujung saya?
Damon

2
@BenSewards Anda bisa menggunakan Bash di Windows menggunakan Windows Subsystem untuk Linux, info lebih lanjut di sini
mjsr

152

Ketenaran Git https://github.com/oleander/git-fame-rb

adalah alat yang bagus untuk mendapatkan penghitungan bagi semua penulis sekaligus, termasuk jumlah file yang dikomit dan dimodifikasi:

sudo apt-get install ruby-dev
sudo gem install git_fame
cd /path/to/gitdir && git fame

Ada juga versi Python di https://github.com/casperdcl/git-fame (disebutkan oleh @fracz):

sudo apt-get install python-pip python-dev build-essential 
pip install --user git-fame
cd /path/to/gitdir && git fame

Output sampel:

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

Tetapi berhati-hatilah: seperti yang disebutkan oleh Jared dalam komentar, melakukannya di repositori yang sangat besar akan memakan waktu berjam-jam. Tidak yakin apakah itu bisa diperbaiki, mengingat itu harus memproses data Git begitu banyak.


1
Ini luar biasa tetapi sangat lambat
Jared Burrows

1
Bekerja dengan baik pada pertengahan 2015 macbook dan proyek Android menengah besar (127k LoC 'adalah). Beberapa menit.
Maxweber

2
@Vincent persen toal loc / commit / file untuk pengguna saat ini.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

1
Ubah cabang, batas waktu, dan kecualikan folder:git fame --branch=dev --timeout=-1 --exclude=Pods/*
jonmecer

1
@AlexanderMills Saya menduga itu karena Anda tidak dapat menghitung garis pada blob
Ciro Santilli 郝海东 冠状 病 六四 事件 事件

103

Saya menemukan yang berikut berguna untuk melihat siapa yang memiliki paling banyak baris yang saat ini dalam basis kode:

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

Jawaban lain sebagian besar terfokus pada garis yang diubah dalam komit, tetapi jika komit tidak bertahan dan ditimpa, mereka mungkin hanya churn. Mantra di atas juga membuat Anda semua komuter diurutkan berdasarkan garis, bukan hanya satu per satu. Anda dapat menambahkan beberapa opsi ke git menyalahkan (-C -M) untuk mendapatkan beberapa angka yang lebih baik yang mempertimbangkan perpindahan file dan perpindahan garis antar file ke dalam akun, tetapi perintah itu mungkin berjalan jauh lebih lama jika Anda melakukannya.

Selain itu, jika Anda mencari baris yang diubah di semua komit untuk semua committer, ikuti skrip kecil ini membantu:

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


31
Saya hendak memberi +1, tapi kemudian saya menyadari bahwa solusinya tergantung dari ruby ​​... :(
mac

3
Anda dapat memodifikasinya agar tidak menggunakan ruby ​​dengan mudah karena saya hanya menggunakan ruby ​​untuk substitusi string. Anda dapat menggunakan perl, sed, python, dll
mmrobins

21
tidak berfungsi untuk saya: -e: 1: di `<main> ': urutan byte tidak valid di UTF-8 (ArgumentError)
Michał Dębski

1
/^.*\((.*?)\s[\d]{4}/seharusnya /^.*?\((.*?)\s[\d]{4}/untuk mencegah pencocokan tanda kurung di sumber sebagai penulis.
Timothy Gu

1
mmm eksekusi saya menunjukkan banyak pengguna yang bahkan tidak ada, karena penguraian buruk. Saya pikir itu bukan jawaban yang bisa diandalkan.
mjsr

92

Untuk menghitung jumlah komit oleh penulis yang diberikan (atau semua penulis) pada cabang tertentu Anda dapat menggunakan git-shortlog ; lihat terutama opsi --numbereddan --summary, misalnya ketika dijalankan pada repositori 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

2
Catatan yang v1.6.4ada di sini dalam contoh ini untuk membuat output menjadi deterministik: akan tetap sama tidak peduli kapan Anda mengkloning dan / atau mengambil dari repositori git.
Jakub Narębski

termasuk v1.6.4memberi saya:fatal: ambiguous argument 'v1.6.4': unknown revision or path not in the working tree.
Vlad the Impala

5
Ah, tidak, saya ketinggalan "ketika dijalankan di repositori git". Agar adil, kebanyakan orang tidak akan menjalankan perintah ini di git repo. Dengan margin yang cukup besar, sebenarnya.
Vlad the Impala

4
git shortlog -sneatau, jika Anda lebih suka tidak menyertakan penggabungangit shortlog -sne --no-merges
Mark Swardstrom

1
@Swards: -sadalah --summary, -nadalah --numbered, dan [baru] -eadalah --emailuntuk menunjukkan email dari penulis (dan menghitung secara terpisah penulis yang sama dengan alamat email yang berbeda, dengan memperhitungkan .mailmapkoreksi). Panggilan bagus tentang --no-merges.
Jakub Narębski

75

Setelah melihat Alex dan Gerty3000 jawaban , saya telah mencoba untuk memperpendek garis satu:

Pada dasarnya, menggunakan numstat git log dan tidak melacak jumlah file diubah.

Git versi 2.1.0 di Mac OSX:

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

Contoh:

Jared Burrows   added lines: 6826, removed lines: 2825, total lines: 4001

Tidak bisa membuat alias dari itu :-(
anak nakal

33

The Jawaban dari AaronM menggunakan shell satu-kapal yang baik, tetapi sebenarnya, masih ada bug lain, di mana ruang akan merusak nama pengguna jika ada jumlah yang berbeda dari ruang putih antara nama pengguna dan tanggal. Nama pengguna yang rusak akan memberikan beberapa baris untuk jumlah pengguna dan Anda harus menjumlahkannya sendiri.

Perubahan kecil ini memperbaiki masalah bagi saya:

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

Perhatikan tanda + yang akan menghabiskan semua spasi putih dari nama hingga tanggal.

Sebenarnya menambahkan jawaban ini sebanyak untuk ingatan saya sendiri seperti untuk membantu orang lain, karena ini setidaknya kedua kalinya saya google subjek :)

  • Sunting 2019-01-23 Ditambahkan --show-emailke git blame -wagregat pada email sebagai gantinya, karena beberapa orang menggunakan Nameformat berbeda pada komputer yang berbeda, dan kadang-kadang dua orang dengan nama yang sama bekerja di git yang sama.

Jawaban ini menggunakan perl tampaknya sedikit lebih baik daripada yang berbasis ruby. Ruby tersedak baris yang bukan teks UTF-8 yang sebenarnya, perl tidak mengeluh. Tetapi apakah perl melakukan hal yang benar? Saya tidak tahu
Stéphane Gourichon

Submodules menghasilkan unsupported file typetetapi selain itu tampaknya berfungsi dengan baik bahkan dengan mereka (itu dilewati)
Vladimír Čunát

24

Berikut ini adalah kalimat singkat yang menghasilkan statistik untuk semua penulis. Ini jauh lebih cepat daripada solusi Dan di atas di https://stackoverflow.com/a/20414465/1102119 (tambang memiliki kompleksitas waktu O (N) daripada O (NM) di mana N adalah jumlah komit, dan M jumlah penulis ).

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
Bagus tapi apa artinya output?
Gary Willoughby

Anda harus menambahkan --no-show-signature, jika tidak, orang yang menandatangani-pgt tidak akan dihitung.
Philihp Busby

2
ins [a] - del [a], ins [a], del [a], a, jadi jika saya benar penyisipan-penghapusan, penyisipan, penghapusan, nama
MrKekson

Bagaimana saya bisa menambahkan perintah ini ke konfigurasi git saya sehingga saya bisa memanggilnya dengan "git count-lines"?
takanuva15

Tidak pernah pikiran, saya pikir itu keluar: 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". (Catatan saya di Windows; Anda mungkin perlu menggunakan berbagai jenis kutipan)
takanuva15

21

@mmrobins @AaronM @ErikZ @JamesMishra menyediakan varian yang semuanya memiliki masalah yang sama: mereka meminta git untuk membuat campuran informasi yang tidak dimaksudkan untuk konsumsi skrip, termasuk konten baris dari repositori pada baris yang sama, kemudian mencocokkan kekacauan dengan regexp .

Ini adalah masalah ketika beberapa baris tidak valid teks UTF-8, dan juga ketika beberapa baris cocok dengan regexp (ini terjadi di sini).

Inilah baris yang dimodifikasi yang tidak memiliki masalah ini. Ia meminta git untuk menampilkan data secara bersih pada baris yang berbeda, yang membuatnya mudah untuk menyaring apa yang kita inginkan dengan kuat:

git ls-files -z | xargs -0n1 git blame -w --line-porcelain | grep -a "^author " | sort -f | uniq -c | sort -n

Anda dapat menangkap string lain, seperti author-mail, committer, dll.

Mungkin pertama-tama lakukan export LC_ALL=C(dengan asumsi bash) untuk memaksa pemrosesan byte-level (ini juga terjadi untuk mempercepat grep dari lokasi berbasis UTF-8).


Garis yang bagus di sana, sangat keren, sehingga Anda dapat dengan mudah mencampurnya, namun ini gagal melakukan apa yang diminta oleh pengirim asli, memberikan hitungan oleh penulis dari git. Tentu Anda bisa menjalankannya dan melakukan wc-l, dll, tetapi kemudian Anda harus mengulangi untuk setiap penulis di repositori.
AaronM

1
@ Harun Saya tidak mengerti kritik Anda. Baris ini AFAIK menampilkan statistik yang sama dengan Anda, hanya lebih kuat. Jadi, jika jawaban saya "gagal melakukan apa yang diminta poster asli, berikan penghitungan oleh penulis dari git", maka milik Anda bahkan lebih. Tolong beri tahu saya.
Stéphane Gourichon

maaf saya salah membaca, saya pikir perintah harus diubah untuk setiap nama penulis yang berbeda. Komentar Anda tentang grep untuk string lain membawa saya ke sana, tetapi itu adalah kesalahpahaman saya.
AaronM

Ini luar biasa. Terima kasih!
Tek

16

Sebuah solusi diberikan dengan ruby ​​di tengah, perl menjadi sedikit lebih tersedia secara default di sini adalah alternatif menggunakan perl untuk baris saat ini oleh penulis.

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
Regex yang diperbarui tidak membuat perbedaan yang berarti, dan itu rusak karena Anda tidak lolos dari paren pertama. Namun, saya dapat melihat beberapa kasus di mana yang sebelumnya saya mungkin menemukan beberapa bit di baris kode untuk menempel. Ini akan bekerja lebih andal: git ls-files -z | xargs -0n1 git menyalahkan -w | perl -n -e '/^.*?\((.*?)\s[\d[{4}/; cetak $ 1, "\ n"' | sort -f | uniq -c | sort -n
AaronM

terima kasih telah mencoba membuat regexp yang lebih andal. Lihat jawaban saya untuk varian stackoverflow.com/a/36090245/1429390 yang
Stéphane Gourichon

13

Selain jawaban Charles Bailey , Anda mungkin ingin menambahkan -Cparameter ke perintah. Kalau tidak, nama file dihitung sebagai banyak tambahan dan penghapusan (sebanyak file memiliki garis), bahkan jika konten file tidak diubah.

Sebagai ilustrasi, berikut adalah komit dengan banyak file yang dipindahkan dari salah satu proyek saya, ketika menggunakan git log --oneline --shortstatperintah:

9052459 Reorganized project structure
 43 files changed, 1049 insertions(+), 1000 deletions(-)

Dan di sini, komit yang sama menggunakan git log --oneline --shortstat -Cperintah yang mendeteksi salinan dan mengganti nama file:

9052459 Reorganized project structure
 27 files changed, 134 insertions(+), 85 deletions(-)

Menurut pendapat saya yang terakhir memberikan pandangan yang lebih realistis tentang seberapa besar dampak seseorang terhadap proyek, karena mengubah nama file adalah operasi yang jauh lebih kecil daripada menulis file dari awal.


2
Ketika saya menjalankan "git log --oneline --shortstat", saya tidak mendapatkan hasil Anda. Saya memiliki daftar komit dengan jumlah edisi tetapi bukan jumlah total. Bagaimana saya bisa mendapatkan jumlah total baris yang diedit di semua repositori git?
Mehdi

12

Anda dapat menggunakan whodid ( https://www.npmjs.com/package/whodid )

$ npm install whodid -g
$ cd your-project-dir

dan

$ whodid author --include-merge=false --path=./ --valid-threshold=1000 --since=1.week

atau ketik saja

$ whodid

maka Anda dapat melihat hasilnya seperti ini

Contribution state
=====================================================
 score  | author
-----------------------------------------------------
 3059   | someguy <someguy@tensorflow.org>
 585    | somelady <somelady@tensorflow.org>
 212    | niceguy <nice@google.com>
 173    | coolguy <coolgay@google.com>
=====================================================

Apa yang dimaksud dengan 'skor'?
user11171

@Volte npm saya hanyalah jalan pintas untuk instal npm
Michiel

Ya saya sadar. Saya -gharus datang sebelum nama paket, pada macOS. Cukup berusaha membantu.
Volte

11

Berikut ini adalah skrip ruby ​​cepat yang mengkoreksi dampak per pengguna terhadap kueri log yang diberikan.

Misalnya, untuk rubinius :

Brian Ford: 4410668
Evan Phoenix: 1906343
Ryan Davis: 855674
Shane Becker: 242904
Alexander Kellett: 167600
Eric Hodel: 132986
Dirkjan Bussink: 113756
...

naskah:

#!/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
Skrip ini hebat, tetapi mengecualikan penulis yang hanya memiliki komitmen satu baris! Untuk memperbaikinya, ubah sebagai berikut: penyisipan perubahan = / (\ d +). * (\ D +) penghapusan / .match (baris)
Larry Gritz

9

ini adalah cara terbaik dan juga memberi Anda gambaran yang jelas tentang jumlah total komitmen oleh semua pengguna

git shortlog -s -n

2
Berguna, tetapi jumlah komit bukan total baris kode
Diolor

5

Saya memberikan modifikasi dari jawaban singkat di atas, tetapi itu tidak cukup untuk kebutuhan saya. Saya harus bisa mengkategorikan baris yang berkomitmen dan baris dalam kode akhir. Saya juga ingin rincian berdasarkan file. Kode ini tidak berulang, itu hanya akan mengembalikan hasil untuk direktori tunggal, tetapi ini adalah awal yang baik jika seseorang ingin melangkah lebih jauh. Salin dan tempel ke file dan buat bisa dieksekusi atau jalankan dengan 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};
}

Saya mendapatkan kesalahan ini: Pembagian ilegal dengan nol di x.pl baris 71.
Vivek Jha

Ditujukan kepada divisi ilegal dengan nol pada baris 71. Pikirkan itu terjadi jika tidak ada pengeditan tetapi beberapa waktu yang lalu saya menulis ini.
AaronM

2

Untuk pengguna windows Anda dapat menggunakan skrip batch berikut yang menghitung baris yang ditambahkan / dihapus untuk penulis yang ditentukan

@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

Ini adalah repo yang bagus yang membuat hidup Anda lebih mudah

git-quick-stats

Pada mac dengan minuman yang diinstal

brew install git-quick-stats

Lari

git-quick-stats

Cukup pilih opsi mana yang Anda inginkan dari daftar ini dengan mengetikkan nomor yang tercantum dan menekan 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

Skrip ini di sini akan melakukannya. Masukkan ke dalam authorhip.sh, chmod + x, dan Anda siap.

#!/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
tidak itu TIDAK AKAN !, Anda memposting ini di tempat lain, itu menghasilkan kesalahan pada mac dan linux, Anda tahu, jenis komputer git dibuat!
Pizzaiola Gorgonzola

1

Simpan log Anda ke dalam file menggunakan:

git log --author="<authorname>" --oneline --shortstat > logs.txt

Untuk pecinta 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')

Output Anda akan seperti:

225        files changed
6751       insertions
1379       deletions

0

Anda ingin Git disalahkan .

Ada opsi --show-stats untuk mencetak beberapa, well, stats.


Saya mencoba blame, tetapi itu tidak benar-benar memberikan statistik yang saya pikir OP butuhkan?
CB Bailey

Terima kasih, ini juga membantu saya dengan .mailmap juga!
Gav

0

Pertanyaannya menanyakan informasi spesifik penulis , tetapi banyak dari jawabannya adalah solusi yang mengembalikan daftar peringkat penulis berdasarkan baris kode mereka yang diubah.

Inilah yang saya cari, tetapi solusi yang ada tidak cukup sempurna. Untuk kepentingan orang-orang yang mungkin menemukan pertanyaan ini melalui Google, saya telah membuat beberapa perbaikan pada mereka dan menjadikannya menjadi skrip shell, yang saya tampilkan di bawah ini. Yang beranotasi (yang akan terus saya pertahankan) dapat ditemukan di Github saya .

Tidak ada dependensi pada Perl atau Ruby. Selanjutnya, spasi putih, penggantian nama, dan pergerakan garis diperhitungkan dalam jumlah perubahan baris. Masukkan saja ini ke dalam file dan berikan repositori Git Anda sebagai parameter pertama.

#!/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

Alat terbaik sejauh ini yang saya identifikasi adalah gitinspector. Ini memberikan laporan yang ditetapkan per pengguna, per minggu dll Anda dapat menginstal seperti di bawah ini dengan npm

npm instal -g gitinspector

Tautan untuk mendapatkan detail lebih lanjut

https://www.npmjs.com/package/gitinspector

https://github.com/ejwa/gitinspector/wiki/Documentation

https://github.com/ejwa/gitinspector

contoh perintahnya adalah

gitinspector -lmrTw 
gitinspector --since=1-1-2017 etc

0

Saya menulis skrip Perl ini untuk menyelesaikan tugas itu.

#!/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;
}

Saya menamainya git-line-changes-by-authordan dimasukkan ke dalam /usr/local/bin. Karena disimpan di jalur saya, saya bisa mengeluarkan perintah git line-changes-by-author --before 2018-12-31 --after 2020-01-01untuk mendapatkan laporan untuk tahun 2019. Sebagai contoh. Dan jika saya salah mengeja nama git akan menyarankan ejaan yang tepat.

Anda mungkin ingin menyesuaikan _get_repo_slugsub untuk hanya menyertakan bagian terakhir dari remote.origin.urlrepo saya yang disimpan project/repodan mungkin tidak.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.