Respuestas:
El resultado del siguiente comando debería ser razonablemente fácil de enviar al script para sumar los totales:
git log --author="<authorname>" --oneline --shortstat
Esto proporciona estadísticas para todos los commits en el HEAD actual. Si desea agregar estadísticas en otras ramas, deberá proporcionarlas como argumentos para git log
.
Para pasar a un script, eliminar incluso el formato "en línea" se puede hacer con un formato de registro vacío, y como comentó Jakub Narębski, --numstat
es otra alternativa. Genera estadísticas por archivo en lugar de por línea, pero es aún más fácil de analizar.
git log --author="<authorname>" --pretty=tformat: --numstat
--numstat
lugar de hacerlo --shortstat
si desea agregar estadísticas un poco más fácilmente.
git help log
me dice que las primeras son líneas agregadas, las segundas líneas borradas.
Esto proporciona algunas estadísticas sobre el autor, modificar según sea necesario.
Usando 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 }' -
Usando Awk en 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 }' -
Hay un nuevo paquete en github que se ve elegante y usa bash como dependencias (probado en linux). Es más adecuado para uso directo en lugar de scripts.
Es git-quick-stats (enlace github) .
Copie git-quick-stats
a una carpeta y agregue la carpeta a la ruta.
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
Uso:
git-quick-stats
gawk
para awk
hacerlo funcionar en el terminal OSX
git clone https://github.com/arzzen/git-quick-stats.git
En caso de que alguien quiera ver las estadísticas de cada usuario en su base de código, un par de mis compañeros de trabajo recientemente inventaron esta horrible frase:
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";}'
(Tarda unos minutos en analizar nuestro repositorio, que tiene alrededor de 10-15k confirmaciones).
michael,: 6057 files changed, 854902 insertions(+), 26973 deletions(-), 827929 net
Git fama https://github.com/oleander/git-fame-rb
es una buena herramienta para obtener el recuento de todos los autores a la vez, incluido el recuento de confirmación y archivos modificados:
sudo apt-get install ruby-dev
sudo gem install git_fame
cd /path/to/gitdir && git fame
También hay una versión de Python en https://github.com/casperdcl/git-fame (mencionado por @fracz):
sudo apt-get install python-pip python-dev build-essential
pip install --user git-fame
cd /path/to/gitdir && git fame
Salida de muestra:
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 |
+------------------------+--------+---------+-------+--------------------+
Pero ten cuidado: como lo mencionó Jared en el comentario, hacerlo en un repositorio muy grande llevará horas. Sin embargo, no estoy seguro de si eso podría mejorarse, teniendo en cuenta que debe procesar tantos datos de Git.
git fame --branch=dev --timeout=-1 --exclude=Pods/*
Encontré lo siguiente útil para ver quién tenía la mayoría de las líneas que estaban actualmente en la base del código:
git ls-files -z | xargs -0n1 git blame -w | ruby -n -e '$_ =~ /^.*\((.*?)\s[\d]{4}/; puts $1.strip' | sort -f | uniq -c | sort -n
Las otras respuestas se han centrado principalmente en las líneas cambiadas en las confirmaciones, pero si las confirmaciones no sobreviven y se sobrescriben, es posible que hayan sido abandonadas. El encantamiento anterior también te permite ordenar todos los confirmadores por líneas en lugar de solo uno a la vez. Puede agregar algunas opciones a git blame (-C -M) para obtener mejores números que tengan en cuenta el movimiento de archivos y el movimiento de línea entre archivos, pero el comando podría ejecutarse mucho más si lo hace.
Además, si está buscando líneas cambiadas en todas las confirmaciones para todos los confirmadores, el siguiente pequeño script es útil:
/^.*\((.*?)\s[\d]{4}/
debe ser /^.*?\((.*?)\s[\d]{4}/
para evitar paréntesis coincidentes en la fuente como autor.
Para contar el número de confirmaciones de un autor determinado (o de todos los autores) en una rama determinada, puede usar git-shortlog ; vea especialmente sus --numbered
y --summary
opciones, por ejemplo, cuando se ejecuta en el repositorio de 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
v1.6.4
está aquí en este ejemplo para hacer que la salida sea determinista: será lo mismo sin importar cuándo clone y / o recupere del repositorio de git.
v1.6.4
me da:fatal: ambiguous argument 'v1.6.4': unknown revision or path not in the working tree.
git shortlog -sne
o, si prefiere no incluir fusionesgit shortlog -sne --no-merges
-s
es --summary
, -n
es --numbered
y [nuevo] -e
es --email
mostrar correos electrónicos de autores (y contar por separado el mismo autor con diferentes direcciones de correo electrónico, teniendo en cuenta las .mailmap
correcciones). Buena llamada sobre --no-merges
.
Después de mirar a Alex y la respuesta de Gerty3000 , he intentado acortar la frase :
Básicamente, usar git log numstat y no realizar un seguimiento de la cantidad de archivos modificados.
Git versión 2.1.0 en 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
Ejemplo:
Jared Burrows added lines: 6826, removed lines: 2825, total lines: 4001
La respuesta de AaronM usando el shell one-liner es buena, pero en realidad, hay otro error, donde los espacios corromperán los nombres de usuario si hay diferentes cantidades de espacios en blanco entre el nombre de usuario y la fecha. Los nombres de usuario corruptos darán varias filas para los recuentos de usuarios y usted debe sumarlos usted mismo.
Este pequeño cambio solucionó el problema para mí:
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
Observe el + after \ s que consumirá todos los espacios en blanco desde el nombre hasta la fecha.
En realidad, agrego esta respuesta tanto para mi propio recuerdo como para ayudar a alguien más, ya que esta es al menos la segunda vez que busco en Google el tema :)
--show-email
a git blame -w
agregado en el correo electrónico, ya que algunas personas usan diferentes Name
formatos en diferentes computadoras, y a veces dos personas con el mismo nombre están trabajando en el mismo git.unsupported file type
pero, de lo contrario, parece funcionar bien incluso con ellos (los omite).
Aquí hay un breve resumen que genera estadísticas para todos los autores. Es mucho más rápido que la solución anterior de Dan en https://stackoverflow.com/a/20414465/1102119 (la mía tiene una complejidad de tiempo O (N) en lugar de O (NM) donde N es el número de confirmaciones y M el número de autores )
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
--no-show-signature
, de lo contrario, las personas que firman sus compromisos no serán contadas.
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"
. (Tenga en cuenta que estoy en Windows; puede que necesite usar diferentes tipos de citas)
@mmrobins @AaronM @ErikZ @JamesMishra proporcionaron variantes que tienen un problema en común: le piden a git que produzca una mezcla de información no destinada al consumo de scripts, incluido el contenido de la línea del repositorio en la misma línea, luego combina el desorden con una expresión regular .
Este es un problema cuando algunas líneas no son texto UTF-8 válido, y también cuando algunas líneas coinciden con la expresión regular (esto sucedió aquí).
Aquí hay una línea modificada que no tiene estos problemas. Solicita a git que genere datos de forma limpia en líneas separadas, lo que facilita el filtrado de lo que queremos de manera sólida:
git ls-files -z | xargs -0n1 git blame -w --line-porcelain | grep -a "^author " | sort -f | uniq -c | sort -n
Puede buscar otras cadenas, como correo de autor, committer, etc.
Quizás primero export LC_ALL=C
(suponiendo bash
) forzar el procesamiento a nivel de bytes (esto también acelera enormemente el grep de las configuraciones regionales basadas en UTF-8).
Se dio una solución con ruby en el medio, perl está un poco más disponible por defecto aquí es una alternativa usando perl para las líneas actuales por 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
Además de la respuesta de Charles Bailey , es posible que desee agregar el -C
parámetro a los comandos. De lo contrario, los cambios de nombre de archivo cuentan como muchas adiciones y eliminaciones (tantas como el archivo tenga líneas), incluso si el contenido del archivo no se modificó.
Para ilustrar, aquí hay un commit con muchos archivos que se mueven de uno de mis proyectos, cuando uso el git log --oneline --shortstat
comando:
9052459 Reorganized project structure
43 files changed, 1049 insertions(+), 1000 deletions(-)
Y aquí el mismo commit usando el git log --oneline --shortstat -C
comando que detecta copias de archivos y renombra:
9052459 Reorganized project structure
27 files changed, 134 insertions(+), 85 deletions(-)
En mi opinión, este último da una visión más realista de cuánto impacto ha tenido una persona en el proyecto, porque renombrar un archivo es una operación mucho más pequeña que escribir el archivo desde cero.
puedes usar whodid ( https://www.npmjs.com/package/whodid )
$ npm install whodid -g
$ cd your-project-dir
y
$ whodid author --include-merge=false --path=./ --valid-threshold=1000 --since=1.week
o simplemente escriba
$ whodid
entonces puedes ver un resultado como este
Contribution state
=====================================================
score | author
-----------------------------------------------------
3059 | someguy <someguy@tensorflow.org>
585 | somelady <somelady@tensorflow.org>
212 | niceguy <nice@google.com>
173 | coolguy <coolgay@google.com>
=====================================================
-g
tenía que llegar antes de que el nombre del paquete, en macOS
. Simplemente tratando de ayudar.
Aquí hay un script rápido de ruby que acota el impacto por usuario en una consulta de registro dada.
Por ejemplo, para rubinius :
Brian Ford: 4410668
Evan Phoenix: 1906343
Ryan Davis: 855674
Shane Becker: 242904
Alexander Kellett: 167600
Eric Hodel: 132986
Dirkjan Bussink: 113756
...
la secuencia de comandos:
#!/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
Proporcioné una modificación de una respuesta breve anterior, pero no fue suficiente para mis necesidades. Necesitaba poder clasificar tanto las líneas confirmadas como las líneas en el código final. También quería un desglose por archivo. Este código no se repite, solo devolverá los resultados para un solo directorio, pero es un buen comienzo si alguien quiere ir más allá. Copie y pegue en un archivo y haga ejecutable o ejecútelo con 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};
}
Para usuarios de Windows, puede usar el siguiente script por lotes que cuenta las líneas agregadas / eliminadas para el autor especificado
@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
git-quick-stats
brew install git-quick-stats
git-quick-stats
Simplemente elija la opción que desea de esta lista escribiendo el número que aparece y presionando 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)
Este script aquí lo hará. Póngalo en authorhip.sh, chmod + x it, y ya está todo listo.
#!/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 ":"
Guarde sus registros en el archivo usando:
git log --author="<authorname>" --oneline --shortstat > logs.txt
Para los amantes de 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')
Sus resultados serían como:
225 files changed
6751 insertions
1379 deletions
Quieres culpar a Git .
Hay una opción --show-stats para imprimir algunas, bueno, estadísticas.
blame
, pero ¿realmente no dio las estadísticas que pensé que necesitaría el OP?
La pregunta para obtener información sobre un determinado autor , pero muchas de las respuestas fueron soluciones que arrojaron listas clasificadas de autores en función de sus líneas de código cambiadas.
Esto era lo que estaba buscando, pero las soluciones existentes no eran del todo perfectas. En interés de las personas que pueden encontrar esta pregunta a través de Google, he realizado algunas mejoras en ellos y los he convertido en un script de shell, que se muestra a continuación. Puede encontrar uno anotado (que continuaré manteniendo) en mi Github .
No hay dependencias ni en Perl ni en Ruby. Además, los espacios en blanco, los cambios de nombre y los movimientos de línea se tienen en cuenta en el recuento de cambio de línea. Simplemente ponga esto en un archivo y pase su repositorio Git como primer parámetro.
#!/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
La mejor herramienta hasta ahora identificada es gitinspector. Proporciona el informe establecido por usuario, por semana, etc. Puede instalar como a continuación con npm
npm install -g gitinspector
Los enlaces para obtener más detalles
https://www.npmjs.com/package/gitinspector
https://github.com/ejwa/gitinspector/wiki/Documentation
https://github.com/ejwa/gitinspector
los comandos de ejemplo son
gitinspector -lmrTw
gitinspector --since=1-1-2017 etc
Escribí este script de Perl para lograr esa tarea.
#!/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;
}
Lo nombré git-line-changes-by-author
y lo puse /usr/local/bin
. Debido a que está guardado en mi camino, puedo emitir el comando git line-changes-by-author --before 2018-12-31 --after 2020-01-01
para obtener el informe para el año 2019. Como ejemplo. Y si tuviera que escribir mal el nombre git sugeriría la ortografía correcta.
Es posible que desee ajustar el _get_repo_slug
sub para que solo incluya la última parte del remote.origin.url
archivo ya que mis repositorios se guardan como project/repo
y es posible que no lo sea.
git://git.lwn.net/gitdm.git
.