Colaboradores Git de cada archivo

Quiero enumerar todos los contribuyentes para cada archivo en el repositorio.

Esto es lo que hago actualmente:

find . | xargs -L 1 git blame -f | cut -d' ' -f 2-4 | sort | uniq

Esto es muy lento. ¿Hay una solución mejor?

preguntado el 31 de julio de 12 a las 11:07

5 Respuestas

Tomando como base la respuesta de ДМИТРИЙ, diría lo siguiente:

git ls-tree -r --name-only master ./ | while read file ; do
    echo "=== $file"
    git log --follow --pretty=format:%an -- $file | sort | uniq
done

La mejora es que sigue el cambio de nombre del archivo en su historial y se comporta correctamente si los archivos contienen espacios (| while read file)

Respondido 31 Jul 12, 14:07

Esto es bastante lento en comparación con la respuesta de igor. Tenemos un depósito enorme. esto toma unos segundos por archivo. - log0

Escribiría un pequeño script que analiza la salida de git log --stat --pretty=format:'%cN'; algo a lo largo de las líneas de:

#!/usr/bin/env perl

my %file;
my $contributor = q();

while (<>) {
    chomp;
    if (/^\S/) {
        $contributor = $_;
    }
    elsif (/^\s*(.*?)\s*\|\s*\d+\s*[+-]+/) {
        $file{$1}{$contributor} = 1;
    }
}

for my $filename (sort keys %file) {
    print "$filename:\n";
    for my $contributor (sort keys %{$file{$filename}}) {
        print "  * $contributor\n";
    }
}

(Escrito rápidamente; no cubre casos como archivos binarios).

Si almacenó este script, por ejemplo, como ~/git-contrib.pl, podrías llamarlo con:

git log --stat=1000,1000 --pretty=format:'%cN' | perl ~/git-contrib.pl

ventaja: llamar git una sola vez, lo que implica que es razonablemente rápido. Desventaja: es un guión separado.

Respondido el 01 de Septiembre de 12 a las 09:09

Esto es rápido pero no informa rutas completas de archivos. - log0

Si su estructura de directorios es demasiado profunda para que los nombres de archivo se corten, simplemente especifique un parámetro de ancho de salida alto arbitrario para el --stat opción, por ejemplo --stat=1000 - Igor

--stat=1000,1000 hizo el trabajo - log0

Nadie: " " igor: ¡Aquí hay un script en Perl! - Sándwich

tldr:

for file in `git ls-tree -r --name-only master ./`; do
    echo $file
    git shortlog -s -- $file | sed -e 's/^\s*[0-9]*\s*//'
done
  1. Puede obtener todos los archivos rastreados en el repositorio con git ls-tree. Find es realmente mala elección.

    Por ejemplo, obtenga una lista de archivos rastreados en la rama master en el directorio actual (./):

    git ls-tree -r --name-only master ./
    
  2. Puede obtener una lista de editores de archivos con get shortlog (git blame es exagerado):

    git shortlog -s -- $file
    

Entonces, para cada archivo de ls-tree respuesta que debe llamar shortlog y modifica su salida como quieras.

Respondido 31 Jul 12, 13:07

+1, es el enfoque correcto, sin embargo, no sigue los cambios de nombre de archivo, y si el nombre de archivo contiene espacio, falla. Ver mi respuesta para arreglar esto - carlosb

git log --pretty=format:"%cn" <filename> | sort | uniq -c

También puedes hacer más con git log, Ej: confirmadores de cada archivo después de cierta fecha (Ej: después de 2018-10-1): git log --after="2018-10-1" --pretty=format:"%cn" <filename> | sort | uniq -c

Ref: https://www.atlassian.com/git/tutorials/git-log

Respondido el 19 de enero de 19 a las 00:01

Esto no responde a la pregunta de OP, OP quería esto para cada archivo y quería recorrer el historial solo una vez, no una vez por archivo. - jthill

No use --stat si no necesita las estadísticas, ¿por qué pedirle que vuelva a ejecutar todas las diferencias y luego elimine todos los resultados? Solo usa --name-only.

git log --all --pretty=%x09%cN --name-only |  awk -F$'\t' '
        NF==2   { name=$2 }
        NF==1   { contribs[ $0 ][ name ] = 1 }
        END     {
                n = asorti(contribs,sorted)
                for ( i=0 ; ++i < n ; ) {
                        file = sorted[i]
                        print file
                        for ( name in contribs[file] ) print "\t"name
                }
        }
'

Respondido el 19 de enero de 19 a las 15:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.