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


Answers

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

Question

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 Wege geben muss, die Anzahl der Commits zu zählen, da Github dies für ihren Impact-Graph macht.




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.







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 ":"



Du willst Git die Schuld geben .

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




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.




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



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



Um die Anzahl der Commits eines bestimmten Autors (oder aller Autoren) in einem bestimmten Zweig zu zählen, können Sie git-shortlog ; 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



Die Answer von AaronM mit dem Shell- AaronM 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 :)




Links