Cómo recuperar la fecha de la última modificación de todos los archivos en un repositorio git

64

Sé cómo recuperar la última fecha de modificación de un solo archivo en un repositorio git:

git log -1 --format="%ad" -- path/to/file

¿Existe una manera simple y eficiente de hacer lo mismo para todos los archivos actualmente presentes en el repositorio?

Eric Bréchemier
fuente

Respuestas:

74

Una respuesta simple sería recorrer cada archivo y mostrar su tiempo de modificación, es decir:

git ls-tree -r --name-only HEAD | while read filename; do
  echo "$(git log -1 --format="%ad" -- $filename) $filename"
done

Esto producirá resultados así:

Fri Dec 23 19:01:01 2011 +0000 Config
Fri Dec 23 19:01:01 2011 +0000 Makefile

Obviamente, puede controlar esto ya que es solo un script bash en este punto, así que siéntase libre de personalizarlo al contenido de su corazón.

Andrew M.
fuente
2
Esperaba que hubiera una opción para obtener una salida combinada en una sola ejecución de git log, pero su respuesta es mejor que la que tenía en mente al usar find. No conocía git-ls-tree, que tiene la ventaja de enumerar solo los archivos almacenados en el repositorio, omitir la carpeta .git e ignorar los archivos. Gracias.
Eric Bréchemier
No hay problema, Eric; estás siguiendo la misma ruta que yo, es decir, haciendo una búsqueda e ignorando el directorio .git. :) Puede haber algunas opciones usando los comandos de fontanería git, pero francamente, esto funciona bastante bien. Si pudiera encontrar alguna forma de obtener la información por archivo de una sola vez, eso funcionaría mejor, pero recuerde, git opera en el estado de las confirmaciones, no en el estado de los archivos individuales.
Andrew M.
11
Recomiendo usar --format = "% ai" si desea marcas de tiempo ordenables en lugar de fechas legibles por humanos.
ThorSummoner
2
Dado que "HEAD" es solo una referencia, puede usar cualquier referencia que desee, ya sea una etiqueta, rama, commit hash, etc.
Andrew M.
1
como dijo @ThorSummoner, use el formato% ai para la fecha, y luego simplemente canalice para ordenar los resultados:git ls-tree -r --name-only HEAD | while read filename; do echo "$(git log -1 --format="%ai" -- $filename) $filename"; done | sort
John Hunt
21

Este enfoque también funciona con nombres de archivo que contienen espacios:

git ls-files -z | xargs -0 -n1 -I{} -- git log -1 --format="%ai {}" {}

Salida de ejemplo:

2015-11-03 10:51:16 -0500 .gitignore
2016-03-30 11:50:05 -0400 .htaccess
2015-02-18 12:20:26 -0500 .travis.yml
2016-04-29 09:19:24 +0800 2016-01-13-Atlanta.md
2016-04-29 09:29:10 +0800 2016-03-03-Elmherst.md
2016-04-29 09:41:20 +0800 2016-03-03-Milford.md
2016-04-29 08:15:19 +0800 2016-03-06-Clayton.md
2016-04-29 01:20:01 +0800 2016-03-14-Richmond.md
2016-04-29 09:49:06 +0800 3/8/2016-Clayton.md
2015-08-26 16:19:56 -0400 404.htm
2016-03-31 11:54:19 -0400 _algorithms/acls-bradycardia-algorithm.htm
2015-12-23 17:03:51 -0500 _algorithms/acls-pulseless-arrest-algorithm-asystole.htm
2016-04-11 15:00:42 -0400 _algorithms/acls-pulseless-arrest-algorithm-pea.htm
2016-03-31 11:54:19 -0400 _algorithms/acls-secondary-survey.htm
2016-03-31 11:54:19 -0400 _algorithms/acls-suspected-stroke-algorithm.htm
2016-03-31 11:54:19 -0400 _algorithms/acls-tachycardia-algorithm-stable.htm
...

La salida se puede ordenar por marca de tiempo de modificación agregando | sortal final:

git ls-files -z | xargs -0 -n1 -I{} -- git log -1 --format="%ai {}" {} | sort
William Entriken
fuente
¿Alguna forma de ordenar esto por fecha y hora de modificación?
Amelio Vazquez-Reina
1
@ AmelioVazquez-Reina: Solo agrega `| ordenar` hasta el final del comando.
dotancohen
2
Esto funciona pero lleva mucho tiempo ...
Guillochon
5

Este es un pequeño ajuste de la respuesta de Andrew M. (No pude comentar su respuesta).

Envuelva el primer $ nombre de archivo entre comillas dobles , para admitir nombres de archivo con espacios incrustados.

git ls-tree -r --name-only HEAD | while read filename; do
    echo "$(git log -1 --format="%ad" -- "$filename") $filename"
done

Salida de muestra:

Tue Jun 21 11:38:43 2016 -0600 subdir/this is a filename with spaces.txt

¡Aprecio que la solución de Andrew (basada en ls-tree ) funciona con repositorios desnudos! (Esto no es cierto para las soluciones que usan archivos ls).

Kevin G.
fuente
También puede omitir el echo: git log -1 --format = "% ad $ filename"
Kevin Lyda
0

Aquí está la versión de concha de pescado de la respuesta de Andrew M, para aquellos que usan pescado.

git ls-tree -r --name-only HEAD | while read -l filename
    printf '%s %s\n' (git log -1 --format="%ai" -- $filename) $filename
end

Lo guardo como una función de pez para facilitar el acceso.

Kevin Cherepski
fuente
0

Para aquellos de nosotros que usamos Windows y PowerShell, la respuesta de Andrew M, con el ajuste legible por computadora:

git ls-tree -r --name-only HEAD | ForEach-Object { "$(git log -1 --format="%ai" -- "$_")`t$_" }

Salida de ejemplo:

2019-05-07 12:00:37 -0500   .editorconfig
2016-07-13 14:03:49 -0500   .gitattributes
2019-05-07 12:00:37 -0500   .gitignore
2018-02-03 22:01:17 -0600   .mailmap
James Skemp
fuente