¿Cómo contar el número de confirmaciones por nombre de ruta de archivo por autor en un repositorio de Git?

5 minutos de lectura

Avatar de usuario de Gary S. Weaver
Gary S. Tejedor

Tiempo git-culpa y contar el número de líneas modificadas por un autor dentro de un repositorio de git son útiles, ¿hay un comando que pueda enumerar todos los nombres de ruta modificados en un repositorio en todas las confirmaciones por un autor o conjunto de autores que puntúe cada archivo por el número de comete por ese autor o conjunto de autores? Por ejemplo, el resultado de ejecutar un comando de este tipo en un repositorio de git clonado sería similar a:

1    /path/to/some/file/in/repo/file1
34   /path/to/some/file/in/repo/file2
3    /path/to/some/other/file/in/repo/anotherfile
...

¡Gracias!

  • ¿Vas a tomar decisiones salariales?

    – Basilevs

    15 de septiembre de 2014 a las 16:18

  • 🙂 No. Solo quería identificar partes del código en las que podría enfocarse, y usar # compromisos por archivo por autor sería una forma de identificar partes del código en las que enfocarse para la transferencia de conocimiento cuando un empleado se va.

    – Gary S. Weaver

    15/09/2014 a las 21:10


  • ¿Está dispuesto a escribir un archivo por lotes? Si es así, podrías usar git rev-list HEAD --count --author=someDude -- somefile.txt para crear una salida de conteo.

    – Shaun Lutin

    9 dic 2014 a las 17:37

Avatar de usuario de Gary S. Weaver
Gary S. Tejedor

Me acabo de dar cuenta de que si usas --name-only para imprimir los nombres de archivo, formato bonito como una cadena vacía, y usar este método para ordenar, unir y ordenar por el mayor número de confirmaciones, en *nix/OS X, podría usar:

git log --name-only --author=John --pretty=format: | sort | uniq -c | sort -nr

Asegúrese de que está utilizando el autor correcto.

Por ejemplo, si estuviéramos tratando de encontrar los autores de DHH en Rails, podríamos hacer:

git log --format="%aN <%aE>" | LC_ALL='C' sort -u | grep avid

y observe que todos los autores de DHH en Rails git repo usan el nombre “David Heinemeier Hansson”. Entonces, entonces podríamos hacer:

git log --name-only --author="David Heinemeier Hansson" --pretty=format: | sort | uniq -c | sort -nr

Que podría generar:

3624 
 611 actionpack/CHANGELOG
 432 activerecord/CHANGELOG
 329 railties/CHANGELOG
 206 activerecord/lib/active_record/base.rb
 195 activesupport/CHANGELOG
 157 actionpack/lib/action_controller/base.rb
 153 railties/Rakefile
 108 activerecord/lib/active_record/associations.rb
  79 actionpack/lib/action_view/helpers/javascript_helper.rb
  75 activerecord/lib/active_record/validations.rb
  74 activerecord/test/base_test.rb
  69 actionmailer/CHANGELOG
  66 railties/lib/rails_generator/generators/applications/app/app_generator.rb
  66 activerecord/Rakefile
  66 actionpack/lib/action_controller/caching.rb
  60 actionpack/lib/action_controller/routing.rb
  59 railties/lib/initializer.rb
  59 actionpack/Rakefile
  57 actionpack/lib/action_controller/request.rb
  ...

Entonces, a partir del 21 de febrero de 2015, había 3624 archivos en el repositorio git de Rails en los que parece que él nunca realizó confirmaciones personalmente, la mayor cantidad de confirmaciones para un archivo fue ActionPack CHANGELOG con 611 confirmaciones, seguidas por ActiveRecord CHANGELOG , y ActiveRecord::Base fue el archivo de Ruby con el que hizo más confirmaciones.

Si desea excluir el número de archivos no tocados de los recuentos, utilice --format= en vez de --pretty=format:p.ej:

git log --name-only --author="David Heinemeier Hansson" --format: | sort | uniq -c | sort -nr

  • Eso es increíble y realmente me ayudó. ¡Gracias!

    –Robert Pankowecki

    16 de agosto de 2017 a las 8:48

Avatar de usuario de Shaun Luttin
Shaun Lutin

Ejemplo con PowerShell

Muestra el recuento de confirmaciones del autor especificado para cada archivo en el árbol de trabajo actual.

Forma corta

$author="shaun";
dir -r | % { New-Object PSObject -Property `
@{ `
   Count = git rev-list HEAD --count --author=$author -- $_.Name; `
   FileName = $_.Name; `
}} `
| sort Count | % { $_.Count + ' -- ' + $_.FileName + ' -- ' + $author; }

Forma larga

$author="shaun"; `
Get-ChildItem -recurse | ForEach-Object `
{ `
   New-Object PSObject -Property `
   @{ `
       Count = git rev-list HEAD --count --author=$author -- $_.Name; `
       FileName = $_.Name; `
    } `
} | ` 
Sort-Object Count | ForEach-Object ` 
{ ` 
   $_.Count + ' -- ' + $_.FileName + ' -- ' + $author; `
} 

notas

  • ` significa continuar el comando en una nueva línea.
  • | significa canalizar los objetos resultantes al siguiente comando.
  • $_.SomeProperty accede a una propiedad desde el objeto canalizado.
  • puede copiar/pegar este directorio en PowerShell, porque el ` las marcas indican una nueva línea.
  • incluir filter-branch para rastrear también archivos eliminados previamente y otras ramas.
  • incluir git log --format="%aN" | sort -u iterar a través de todos los autores del proyecto

Producción

0 -- blame.txt~ -- shaun
0 -- .blame.txt.un~ -- shaun
1 -- GitBook-GitTools-06-RewritingHistory.asc -- shaun
1 -- GitBook-GitTools-05-Searching.asc -- shaun
1 -- GitBook-GitTools-03-StashingAndCleaning.asc -- shaun
1 -- GitBook-GitTools-07-ResetDemystified.asc -- shaun
1 -- README.md -- shaun
1 -- LICENSE -- shaun
1 -- GitBook-GitTools-09-Rerere.asc -- shaun
1 -- GitBook-GitBranching-Rebasing.asc -- shaun
1 -- blame2.txt -- shaun
1 -- GitBook-GettingStarted-FirstTimeSetup.asc -- shaun
1 -- GitBook-GitTools-02-InteractiveStaging.asc -- shaun
1 -- GitBook-GitTools-01-RevisionSelection.asc -- shaun
1 -- GitBook-GitInternals-Maintenance.asc -- shaun
2 -- goals.asc -- shaun
2 -- GitBook-GitTools-10-Debugging.asc -- shaun
3 -- blame.txt -- shaun
6 -- GitBook-GitTools-08-AdvancedMerging.asc -- shaun

  • ¿Como funciona esto? Me gustaría modificarlo para obtener confirmaciones por directorio de nivel superior en el repositorio, o al menos obtener la ruta completa de cada archivo.

    – Macke

    18 de febrero de 2016 a las 13:02

  • Agregué una forma larga de PowerShell para usted. Déjame saber si tienes más preguntas.

    – Shaun Lutin

    18 de febrero de 2016 a las 17:05

Descubrí que sería útil agregar este alias de git a .gitconfig:

# list commit counts by file
cc = "!cd ${GIT_PREFIX:-./}; git log --name-only --format= \"$@\" | sort | uniq -c | sort -nr | head -30 #"
# list commit counts by folder
ccf = "!cd ${GIT_PREFIX:-./}; git log --name-only --format= \"$@\" | rev | cut -d"https://stackoverflow.com/" -f2- | rev | sort | uniq -c | sort -nr | head -30 #"

Y luego puedes usar los mismos argumentos que git logp.ej

git cc --author=hank --since="1 year ago" -- path/to/some/folder

¿Ha sido útil esta solución?