tag - qué tipos de etiquetas existen en git
¿Cómo contar las líneas totales cambiadas por un autor específico en un repositorio Git? (21)
@mmrobins @AaronM @ErikZ @JamesMishra proporcionó 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, incluidos los contenidos de línea del repositorio en la misma línea, y luego haga coincidir el lío con una expresión regular .
Este es un problema cuando algunas líneas no son válidas para el texto UTF-8, 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 muestre datos de forma limpia en líneas separadas, lo que facilita el filtrado de lo que queremos de forma sólida:
git ls-files -z | xargs -0n1 git blame -w --line-porcelain | grep -a "^author " | sort -f | uniq -c | sort -n
Puede grep para otras cadenas, como autor-correo, comentarista, etc.
Quizás primero export LC_ALL=C
(suponiendo que bash
) para forzar el procesamiento de nivel de byte (esto también sucede para acelerar tremendamente la grep de las configuraciones regionales basadas en UTF-8).
¿Hay un comando que pueda invocar que contará las líneas cambiadas por un autor específico en un repositorio Git? Sé que debe haber formas de contar el número de confirmaciones, ya que Github hace esto para su gráfico de impacto.
Además de la respuesta de Charles Bailey , es posible que desee agregar el parámetro -C
a los comandos. De lo contrario, los nombres de archivo cuentan como un montón de adiciones y eliminaciones (tantas como el archivo tenga líneas), incluso si el contenido del archivo no se modificó.
Para ilustrar, aquí hay una confirmación con muchos archivos que se mueven alrededor de uno de mis proyectos, al usar el comando git log --oneline --shortstat
:
9052459 Reorganized project structure
43 files changed, 1049 insertions(+), 1000 deletions(-)
Y aquí el mismo commit usando el comando git log --oneline --shortstat -C
que detecta copias de archivos y renombra:
9052459 Reorganized project structure
27 files changed, 134 insertions(+), 85 deletions(-)
En mi opinión, este último ofrece una visión más realista de cuánto impacto ha tenido una persona en el proyecto, porque cambiar el nombre de un archivo es una operación mucho más pequeña que escribir el archivo desde cero.
Aquí hay un breve resumen que produce estadísticas para todos los autores. Es mucho más rápido que la solución de Dan anterior en https://.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
Aquí hay una secuencia de comandos rápida de ruby que acentúa 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
Después de ver la respuesta de Alex y Gerty3000 , he tratado de acortar la frase de una sola línea:
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
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 crearon 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 repo, que tiene alrededor de 10-15k confirmados).
Encontré que lo siguiente es útil para ver quién tiene la mayoría de las líneas que estaban actualmente en el código base:
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 líneas cambiadas en confirmaciones, pero si las confirmaciones no sobreviven y se sobrescriben, es posible que simplemente hayan sido batidas. El encantamiento anterior también hace que todos los comisarios se clasifiquen por líneas en lugar de solo uno a la vez. Puede agregar algunas opciones para echarle la culpa (-C -M) para obtener algunos números mejores que tengan en cuenta el movimiento de archivos y el movimiento de línea entre archivos, pero el comando puede durar 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:
Esta es la mejor manera y también le brinda una imagen clara del número total de confirmaciones de todos los usuarios.
git shortlog -s -n
Este script aquí lo hará. Ponlo en authorship.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 ":"
Esto da algunas estadísticas sobre el autor, modifique 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 }'' -
EDITAR (2017)
Hay un nuevo paquete en github que parece elegante y usa bash como dependencias (probado en linux). Es más adecuado para el uso directo en lugar de scripts.
Es git-quick-stats (enlace github) .
Copie git-quick-stats
en una carpeta y agregue la carpeta a la ruta.
mkdir ~/source
cd ~/source
git clone [email protected]: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
Guarde sus registros en el archivo utilizando:
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'')
Tus salidas serían como:
225 files changed
6751 insertions
1379 deletions
La Answer 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 dañados darán varias filas para los recuentos de usuarios y tendrá que resumirlos usted mismo.
Este pequeño cambio solucionó el problema para mí:
git ls-files -z | xargs -0n1 git blame -w | perl -n -e ''/^.*?/((.*?)/s+[/d]{4}/; print $1,"/n"'' | sort -f | uniq -c | sort -n
Observe el + después de / s que consumirá todos los espacios en blanco desde el nombre hasta la fecha.
En realidad, agregando esta respuesta tanto para mi recuerdo como para ayudar a alguien más, ya que es al menos la segunda vez que busco el tema en Google :)
La mejor herramienta que he identificado hasta ahora es gitinspector. Da el informe del conjunto por usuario, por semana, etc. Puedes instalarlo como abajo 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
comandos de ejemplo son
gitinspector -lmrTw
gitinspector --since=1-1-2017 etc
La pregunta pedía información sobre un autor específico , pero muchas de las respuestas eran soluciones que devolvían listas de autores clasificadas según sus líneas de código modificadas.
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 y las he convertido en un script de shell, que se muestra a continuación. Se 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 renombrados y los movimientos de línea se tienen en cuenta en el recuento de cambio de línea. Simplemente coloque 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 salida del siguiente comando debe ser razonablemente fácil de enviar al script para sumar los totales:
git log --author="<authorname>" --oneline --shortstat
Esto da estadísticas para todos los compromisos en el HEAD actual. Si desea agregar estadísticas en otras sucursales, deberá proporcionarlas como argumentos para git log
.
Para pasar a un script, eliminar incluso el formato "oneline" se puede hacer con un formato de registro vacío, y como comenta Jakub Narębski, --numstat
es otra alternativa. Genera estadísticas por archivo en lugar de por línea, pero es incluso más fácil de analizar.
git log --author="<authorname>" --pretty=tformat: --numstat
Para contar el número de confirmaciones realizadas por un autor determinado (o todos los autores) en una rama determinada, puede utilizar git-shortlog ; vea especialmente sus opciones --numbered
y --summary
, por ejemplo, cuando se ejecuta en el repositorio 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
Proporcioné una modificación de una breve respuesta anterior, pero no fue suficiente para mis necesidades. Necesitaba poder clasificar tanto las líneas comprometidas como las líneas en el código final. También quería un desglose por archivo. Este código no es recurrente, solo devolverá los resultados para un solo directorio, pero es un buen comienzo si alguien quisiera ir más allá. Copie y pegue en un archivo y haga un 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};
}
Quieres culpar a Git .
Hay una opción --show-stats para imprimir algunas, bueno, estadísticas.
Una solución se dio con ruby en el medio, perl está un poco más disponible por defecto aquí es una alternativa que utiliza 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
puede 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 escribe
$ whodid
entonces puedes ver un resultado como este
Contribution state
=====================================================
score | author
-----------------------------------------------------
3059 | someguy <[email protected]>
585 | somelady <[email protected]>
212 | niceguy <[email protected]>
173 | coolguy <[email protected]>
=====================================================
Git fame https://github.com/oleander/git-fame-rb
es una buena herramienta para obtener el recuento de todos los autores a la vez, incluidos los recuentos 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 tenga cuidado: como lo mencionó Jared en el comentario, hacerlo en un gran repositorio llevará horas. No estoy seguro si eso podría mejorarse, considerando que debe procesar tanta información de Git.