Come recuperare la data dell'ultima modifica di tutti i file in un repository git


64

So come recuperare l'ultima data di modifica di un singolo file in un repository git:

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

Esiste un modo semplice ed efficace per fare lo stesso per tutti i file attualmente presenti nel repository?

Risposte:


74

Una semplice risposta sarebbe quella di scorrere attraverso ogni file e visualizzare il suo tempo di modifica, ovvero:

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

Questo produrrà output in questo modo:

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

Ovviamente, puoi controllarlo dal momento che è solo uno script bash a questo punto - quindi sentiti libero di personalizzare il contenuto del tuo cuore!


2
Speravo che ci fosse un'opzione per ottenere un output combinato in una singola esecuzione di git log, ma la tua risposta è migliore di quella che avevo in mente usando find. Non conoscevo git-ls-tree, che ha il vantaggio di elencare solo i file archiviati nel repository, saltando la cartella .git e ignorando i file. Grazie.
Eric Bréchemier,

Nessun problema, Eric; stai seguendo lo stesso percorso che ho fatto, ovvero facendo una ricerca e ignorando la directory .git! :) Ci possono essere alcune opzioni usando i comandi idraulici git, ma francamente, funziona abbastanza bene. Se potessi trovare un modo per ottenere le informazioni su una base per file in una sola volta, ciò funzionerebbe meglio - ma ricorda, git opera sullo stato dei commit, non sullo stato dei singoli file.
Andrew M.

11
Ti consiglio di usare --format = "% ai" se vuoi timestamp ordinabili anziché date leggibili dall'uomo.
ThorSummoner,

2
Poiché "HEAD" è solo un riferimento, è possibile utilizzare qualsiasi riferimento desiderato, sia esso un tag, ramo, commit hash, ecc.
Andrew M.

1
come ha detto @ThorSummoner, usa il formato% ai per data, quindi esegui l'ordinamento per ordinare i risultati:git ls-tree -r --name-only HEAD | while read filename; do echo "$(git log -1 --format="%ai" -- $filename) $filename"; done | sort
John Hunt,

21

Questo approccio funziona anche con nomi di file che contengono spazi:

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

Esempio di output:

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

L'output può essere ordinato in base al timestamp di modifica aggiungendo | sortalla fine:

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

Un modo per ordinarlo in base al timestamp di modifica?
Amelio Vazquez-Reina,

1
@ AmelioVazquez-Reina: basta aggiungere `| ordina` fino alla fine del comando.
dotancohen,

2
Funziona ma richiede molto tempo ...
Guillochon,

5

Questa è una piccola modifica della risposta di Andrew M. (Non sono stato in grado di commentare la sua risposta.)

Avvolgere il primo $ nomefile tra virgolette doppie , al fine di supportare i nomi di file con spazi incorporati.

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

Uscita campione:

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

Apprezzo che la soluzione di Andrew (basata su ls-tree ) funzioni con repository nudi! (Questo non è vero per le soluzioni che usano ls-files.)


Puoi anche saltare l'eco: git log -1 --format = "% ad $ nomefile"
Kevin Lyda,

0

Ecco la versione conchiglia di pesce della risposta di Andrew M, per coloro che usano il pesce.

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

Conservo questo come una funzione di pesce per un facile accesso.


0

Per quelli di noi che usano Windows e PowerShell, la risposta di Andrew M, con il tweak leggibile dal computer:

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

Esempio di output:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.