Jak pobrać datę ostatniej modyfikacji wszystkich plików w repozytorium git

64

Wiem, jak pobrać datę ostatniej modyfikacji pojedynczego pliku w repozytorium git:

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

Czy istnieje prosty i skuteczny sposób, aby zrobić to samo dla wszystkich plików obecnych w repozytorium?

Eric Bréchemier
źródło

Odpowiedzi:

74

Prostą odpowiedzią byłoby powtórzenie każdego pliku i wyświetlenie czasu jego modyfikacji, tj .:

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

To da wynik w następujący sposób:

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

Oczywiście możesz to kontrolować, ponieważ w tym momencie jest to tylko skrypt bashowy - więc dostosuj go do swoich potrzeb!

Andrew M.
źródło
2
Miałem nadzieję, że istnieje opcja uzyskania połączonego wyniku w jednym uruchomieniu git log, ale twoja odpowiedź jest lepsza niż ta, o której myślałem przy użyciu find. Nie znałem git-ls-tree, który ma tę zaletę, że wyświetla listę tylko plików przechowywanych w repozytorium, pomijając folder .git i pliki ignorowane. Dzięki.
Eric Bréchemier
Nie ma problemu, Eric; podążasz tą samą trasą, co ja - tzn. robisz wyszukiwanie i ignorujesz katalog .git! :) Mogą istnieć pewne opcje przy użyciu poleceń git, ale szczerze mówiąc, działa to całkiem dobrze. Gdybyś mógł znaleźć sposób na uzyskanie informacji na temat poszczególnych plików jednocześnie, działałoby to najlepiej - pamiętaj jednak, że git działa w stanie zatwierdzeń, a nie w stanie poszczególnych plików.
Andrew M.,
11
Polecam użycie --format = "% ai", jeśli chcesz sortowalne znaczniki czasu zamiast dat czytelnych dla ludzi.
ThorSummoner
2
Ponieważ „HEAD” jest tylko odnośnikiem, możesz użyć dowolnego odnośnika, niezależnie od tego, czy jest to tag, gałąź, hash zatwierdzenia itp.
Andrew M.
1
jak powiedział @ThorSummoner, użyj formatu% ai dla daty, a następnie po prostu potokuj, aby posortować wyniki:git ls-tree -r --name-only HEAD | while read filename; do echo "$(git log -1 --format="%ai" -- $filename) $filename"; done | sort
John Hunt
21

To podejście działa również w przypadku nazw plików zawierających spacje:

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

Przykładowe dane wyjściowe:

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

Dane wyjściowe można sortować według znacznika czasu modyfikacji, dodając | sortna końcu:

git ls-files -z | xargs -0 -n1 -I{} -- git log -1 --format="%ai {}" {} | sort
William Entriken
źródło
Jakiś sposób, aby to posortować według znacznika czasu modyfikacji?
Amelio Vazquez-Reina
1
@ AmelioVazquez-Reina: Wystarczy dodać `| sort` na końcu polecenia.
dotancohen
2
To działa, ale zajmuje dużo czasu ...
Guillochon
5

To jest drobna poprawka odpowiedzi Andrew M. (Nie mogłem skomentować jego odpowiedzi.)

Zawiń pierwszą nazwę pliku $ w cudzysłów , aby obsługiwać nazwy plików z osadzonymi spacjami.

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

Przykładowe dane wyjściowe:

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

Rozumiem, że rozwiązanie Andrew (oparte na ls-tree ) działa z nagimi repozytoriami! (Nie dotyczy to rozwiązań wykorzystujących pliki ls.)

Kevin G.
źródło
Możesz także pominąć echo: git log -1 --format = "% ad $ filename"
Kevin Lyda
0

Oto wersja odpowiedzi Andrew M dla skorupek ryb dla tych, którzy używają ryb.

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

Przechowuję to jako funkcję ryby dla łatwego dostępu.

Kevin Cherepski
źródło
0

Dla tych z nas korzystających z Windows i PowerShell, odpowiedź Andrew M, z poprawką czytelną dla komputera:

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

Przykładowe dane wyjściowe:

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
źródło