2012-07-31 8 views
8

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

Aquí es actualmente lo que hago:

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

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

Respuesta

4

Escribo un pequeño script que analiza el resultado 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 con la misma rapidez; no cubre casos como archivos binarios.)

Si almacenó este script, por ejemplo, como ~/git-contrib.pl, que se podría llamar con:

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

Ventaja: llame al git solo una vez, lo que implica que es razonablemente rápido. Desventaja: es un script separado.

+0

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

+0

Si la estructura de su directorio es demasiado profunda para que los nombres de los archivos se corten, simplemente especifique un parámetro de alto ancho de salida arbitrario para la opción '--stat', p. Ej. '--stat = 1000' – igor

+0

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

2

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. Usted puede obtener toda rastreó los archivos en el repositorio con git ls-tree. Find es realmente una mala elección.

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

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

    git shortlog -s -- $file 
    

Por lo tanto, para cada archivo de respuesta ls-tree debe llamar al shortlog y mod ify su resultado como quieras.

+0

+ 1, es el enfoque correcto, sin embargo, no sigue el cambio de nombre de archivo, y si el nombre del archivo contiene espacio, falla. Vea mi respuesta para corregir este – CharlesB

5

Tomando la respuesta de ДМИТРИЙ como base, 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 

Enhancement es que sigue el expediente de cambiar el nombre de su historia, y se comporta correctamente si los archivos contienen espacios (| while read file)

+0

Esto es bastante lento en comparación con igor answer. Tenemos un gran repositorio. esto toma unos segundos por archivo. – log0

Cuestiones relacionadas