Wie man die Gesamtlinien zählt, die von einem bestimmten Autor in einem GIT-Ablagefach geändert werden?

Gibt es einen Befehl, den ich aufrufen kann, der die Zeilen zählt, die von einem bestimmten Autor in einem Git-Repository geändert wurden? Ich weiß, dass es Möglichkeiten geben muss, die Anzahl der Commits zu zählen, da Github dies für ihren Impact-Graph macht.

   

Die Ausgabe des folgenden Befehls sollte relativ einfach an das Skript gesendet werden können, um die Gesamtsummen zu addieren:

 git log --author="" --oneline --shortstat 

Dies gibt Statistiken für alle Commits auf dem aktuellen HEAD. Wenn Sie Statistiken in anderen Zweigen hinzufügen möchten, müssen Sie sie als Argumente für git log .

Für die Übergabe an ein Skript kann auch das “oneline” -Format mit einem leeren Protokollformat erstellt werden, und – wie von Jakub Narębski kommentiert – ist --numstat eine weitere Alternative. Es generiert pro-Datei- statt pro-Zeile-Statistiken, ist aber noch einfacher zu parsen.

 git log --author="" --pretty=tformat: --numstat 

Dies gibt einige Statistiken über den Autor, ändern Sie wie erforderlich.

Gawk benutzen:

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

Verwenden von Awk unter 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 }' - 

BEARBEITEN (2017)

Es gibt ein neues Paket auf github, das glatt aussieht und Bash als Abhängigkeiten verwendet (getestet unter Linux). Es ist eher für die direkte Verwendung als für Skripts geeignet.

Es ist git-quick-stats (GitHub-Link) .

Kopieren Sie git-quick-stats in einen Ordner und fügen Sie den Ordner zum Pfad hinzu.

 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 

Verwendung:

 git-quick-stats 

Bildbeschreibung hier eingeben

Falls jemand die Statistiken für jeden Benutzer in seiner Codebasis sehen möchte, haben kürzlich ein paar meiner Kollegen diesen schrecklichen Einzeiler gefunden:

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

(Nimmt ein paar Minuten, um unsere Repo zu durchforsten, die etwa 10-15k Commits hat.)

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

ist ein nettes Tool, um die Anzahl aller Autoren auf einmal zu ermitteln, einschließlich der Anzahl der Commits und der modifizierten Dateien:

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

Es gibt auch eine Python-Version unter https://github.com/casperdcl/git-fame (von @fracz erwähnt):

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

Beispielausgabe:

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

Aber seien Sie gewarnt: Wie von Jared im Kommentar erwähnt, wird es Stunden dauern, es auf einem sehr großen Repository zu tun. Nicht sicher, ob das verbessert werden könnte, wenn man bedenkt, dass es so viele Git-Daten verarbeiten muss.

Ich fand Folgendes nützlich, um zu sehen, wer die meisten Zeilen hatte, die sich zur Zeit in der Codebasis befanden:

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

Die anderen Antworten haben sich hauptsächlich auf Zeilen konzentriert, die sich in Commits geändert haben, aber wenn Commits nicht überleben und überschrieben werden, könnten sie einfach Abwanderung gewesen sein. Die obige Beschwörung bringt euch auch alle Committer sortiert nach Linien statt nur einer nach dem anderen. Sie können einige Optionen hinzufügen, um Schuldzuweisungen (-C-M) zu veranlassen, um bessere Zahlen zu erhalten, die Dateibewegungen und Zeilenbewegungen zwischen Dateien berücksichtigen, aber der Befehl könnte viel länger laufen, wenn Sie dies tun.

Wenn Sie nach Zeilen suchen, die in allen Commits für alle Committer geändert wurden, ist das folgende kleine Skript hilfreich:

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

Um die Anzahl der Commits eines bestimmten Autors (oder aller Autoren) in einem bestimmten Zweig zu zählen, können Sie git-shortlog verwenden ; siehe insbesondere die Optionen --numbered und --summary , zB wenn sie auf dem git-Repository ausgeführt werden:

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

Nachdem ich die Antwort von Alex und Gerty3000 angeschaut habe , habe ich versucht, den One-Liner zu verkürzen:

Im Grunde verwendet git log numstat und nicht die Anzahl der Dateien zu verfolgen geändert.

Git Version 2.1.0 unter 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 

Beispiel:

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

Die Antwort von AaronM mit dem Shell- Einzeiler ist gut, aber tatsächlich gibt es noch einen weiteren Fehler, bei dem Leerzeichen die Benutzernamen verfälschen, wenn zwischen dem Benutzernamen und dem Datum unterschiedliche Leerzeichen liegen. Die beschädigten Benutzernamen geben mehrere Zeilen für Benutzerzählungen und Sie müssen sie selbst zusammenfassen.

Diese kleine Änderung hat das Problem für mich behoben:

 git ls-files -z | xargs -0n1 git blame -w | perl -n -e '/^.*?\((.*?)\s+[\d]{4}/; print $1,"\n"' | sort -f | uniq -c | sort -n 

Beachten Sie das + nach \ s, das alle Leerzeichen vom Namen bis zum Datum verbraucht.

Ich füge diese Antwort sowohl für meine eigene Erinnerung als auch für meine Hilfe hinzu, da dies zumindest das zweite Mal ist, dass ich das Thema google 🙂

@mmrobins @AaronM @ErikZ @JamesMishra stellte Varianten zur Verfügung, die alle ein Problem gemeinsam haben: Sie fordern git auf, eine Mischung aus Informationen zu erzeugen, die nicht für Skriptkonsum gedacht sind, einschließlich Zeileninhalt aus dem Repository in der gleichen Zeile, dann passen Sie das Chaos mit einem regulären Ausdruck an .

Dies ist ein Problem, wenn einige Zeilen kein gültiger UTF-8-Text sind und auch wenn einige Zeilen mit dem regulären Ausdruck übereinstimmen (dies ist hier passiert).

Hier ist eine modifizierte Zeile, die diese Probleme nicht hat. Es fordert git auf, Daten sauber in separaten Zeilen auszugeben, was es einfach macht, das zu filtern, was wir robust haben wollen:

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

Sie können nach anderen Zeichenfolgen wie Autor-Mail, Committer usw. suchen.

Vielleicht export LC_ALL=C zuerst export LC_ALL=C ( bash vorausgesetzt), um die Verarbeitung auf Byte-Ebene zu erzwingen (dies beschleunigt auch grep enorm von den UTF-8-basierten Gebietsschemas).

Hier ist ein kurzer One-Liner, der Statistiken für alle Autoren produziert. Es ist viel schneller als Dans Lösung oben bei https://stackoverflow.com/a/20414465/1102119 (meine Zeitkomplexität O (N) statt O (NM), wobei N die Anzahl der Commits und M die Anzahl der Autoren ist ).

 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 

Eine Lösung wurde mit Ruby in der Mitte gegeben, Perl ist ein wenig mehr standardmäßig verfügbar ist hier eine Alternative mit Perl für aktuelle Zeilen von Autor.

 git ls-files -z | xargs -0n1 git blame -w | perl -n -e '/^.*\((.*?)\s*[\d]{4}/; print $1,"\n"' | sort -f | uniq -c | sort -n 

Zusätzlich zu Charles Baileys Antwort möchten Sie möglicherweise den Parameter -C den Befehlen hinzufügen. Ansonsten zählen Dateiumbenennungen als viele Hinzufügungen und Entfernungen (so viele wie die Datei Zeilen hat), auch wenn der Dateiinhalt nicht geändert wurde.

Um dies zu verdeutlichen, hier ist ein Commit mit vielen Dateien, die von einem meiner Projekte verschoben werden, wenn git log --oneline --shortstat Befehl git log --oneline --shortstat :

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

Und hier das gleiche Commit mit dem Befehl git log --oneline --shortstat -C , der Dateikopien erkennt und umbenennt:

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

Meiner Meinung nach gibt letzteres eine realistischere Ansicht darüber, wie viel Einfluss eine Person auf das Projekt hatte, weil das Umbenennen einer Datei eine viel kleinere Operation ist als das Schreiben der Datei von Grund auf.

Hier ist ein kurzes Ruby-Skript, das den Einfluss pro Benutzer auf eine bestimmte Protokollabfrage erhöht.

Zum Beispiel für Rubyius :

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

das Skript:

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

Ich habe oben eine Änderung einer kurzen Antwort gegeben, aber es war nicht ausreichend für meine Bedürfnisse. Ich musste in der Lage sein, beide festgeschriebenen Zeilen und Zeilen im endgültigen Code zu kategorisieren. Ich wollte auch eine Durchsuchung nach Akten. Dieser Code wird nicht recursed, es gibt nur die Ergebnisse für ein einzelnes Verzeichnis zurück, aber es ist ein guter Anfang, wenn jemand weiter gehen wollte. Kopieren und fügen Sie sie in eine Datei ein und machen Sie sie ausführbar oder führen Sie sie mit Perl aus.

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

Dies ist der beste Weg, und es gibt Ihnen auch ein klares Bild der Gesamtzahl der Commits durch den Benutzer

 git shortlog -s -n 

Sie können whodid verwenden ( https://www.npmjs.com/package/whodid )

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

und

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

oder einfach eingeben

 $ whodid 

dann können Sie das Ergebnis sehen

 Contribution state ===================================================== score | author ----------------------------------------------------- 3059 | someguy  585 | somelady  212 | niceguy  173 | coolguy  ===================================================== 

Dieses Skript hier wird es tun. Setzen Sie es in authorship.sh, chmod + x, und Sie sind fertig.

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

Speichern Sie Ihre Logs in Datei mit:

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

Für Python-Liebhaber:

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

Ihre Ausgaben wären wie folgt:

 225 files changed 6751 insertions 1379 deletions 

Du willst Git die Schuld geben .

Es gibt eine Option –show-stats, um einige, naja, Statistiken zu drucken.

Die Frage wurde nach Informationen zu einem bestimmten Autor gestellt, aber viele der Antworten waren Lösungen, die Ranglisten von Autoren basierend auf ihren Codezeilen änderten.

Das war, was ich suchte, aber die vorhandenen Lösungen waren nicht ganz perfekt. Im Interesse von Leuten, die diese Frage über Google finden können, habe ich einige Verbesserungen an ihnen vorgenommen und sie zu einem Shell-Skript gemacht, das ich unten zeige. Eine annotierte (die ich weiterhin pflegen werde) kann auf meinem Github gefunden werden .

Es gibt keine Abhängigkeiten zu Perl oder Ruby. Darüber hinaus werden Leerzeichen, Umbenennungen und Zeilenbewegungen in der Zeilenwechselzählung berücksichtigt. Legen Sie das einfach in eine Datei und übergeben Sie Ihr Git-Repository als ersten Parameter.

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

Das beste Tool, das ich bisher identifiziert habe, ist gitispector. Es gibt den eingestellten Bericht pro Benutzer, pro Woche usw. Sie können wie folgt mit npm installieren

npm install -g gitinspector

Die Links, um mehr Details zu erhalten

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

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

https://github.com/ejwa/gitinspector

Beispielbefehle sind

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