tipos tag remove qué existen etiquetas crear git command-line statistics repository

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:

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


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