Как получить дату последней модификации всех файлов в репозитории git

64

Я знаю, как получить дату последнего изменения одного файла в репозитории git:

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

Есть ли простой и эффективный способ сделать то же самое для всех файлов, присутствующих в настоящее время в хранилище?

Эрик Брехемье
источник

Ответы:

74

Простой ответ - перебирать каждый файл и отображать время его модификации, а именно:

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

Это даст результат примерно так:

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

Очевидно, что вы можете контролировать это, так как это всего лишь сценарий bash на данный момент - так что не стесняйтесь настраивать по своему вкусу!

Андрей М.
источник
2
Я надеялся, что была возможность получить комбинированный вывод за один запуск git log, но ваш ответ лучше, чем тот, который я имел в виду, используя find. Я не знал git-ls-tree, который имеет преимущество в том, что перечисляет только файлы, хранящиеся в хранилище, пропуская папку .git и игнорируя файлы. Благодарю.
Эрик Брехемье
Нет проблем, Эрик; вы идете по тому же маршруту, что и я - то есть делаете поиск и игнорируете каталог .git! :) Могут быть некоторые варианты, использующие команды git plumbing, но, честно говоря, это работает довольно хорошо. Если бы вы могли найти какой-то способ получить информацию для каждого файла одновременно, это было бы лучше всего - но помните, git работает с состоянием коммитов, а не с состоянием отдельных файлов.
Андрей М.
11
Я рекомендую использовать --format = "% ai", если вы хотите сортировать метки времени вместо удобочитаемых дат.
ThorSummoner
2
Поскольку «HEAD» - это просто ссылка, вы можете использовать любую ссылку, какую захотите, будь то тег, ветвь, хеш коммита и т. Д.
Эндрю М.
1
как сказал @ThorSummoner, используйте формат даты% ai для даты, а затем просто трубу для сортировки результатов:git ls-tree -r --name-only HEAD | while read filename; do echo "$(git log -1 --format="%ai" -- $filename) $filename"; done | sort
Джон Хант
21

Этот подход также работает с именами файлов, которые содержат пробелы:

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

Пример вывода:

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

Вывод можно отсортировать по метке времени модификации, добавив | sortв конец:

git ls-files -z | xargs -0 -n1 -I{} -- git log -1 --format="%ai {}" {} | sort
Уильям Энтрикен
источник
Любой способ получить это отсортировано по метке времени модификации?
Амелио Васкес-Рейна
1
@ AmelioVazquez-Reina: Просто добавьте `| sort` до конца команды.
dotancohen
2
Это работает, но занимает много времени ...
Гильохон
5

Это небольшой трюк с ответом Эндрю М. (Я не смог прокомментировать его ответ.)

Оберните первое $ filename в двойные кавычки , чтобы поддерживать имена файлов со встроенными пробелами.

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

Образец вывода:

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

Я ценю, что решение Эндрю (основанное на ls-tree ) работает с голыми репозиториями! (Это не относится к решениям, использующим ls-файлы.)

Кевин Г.
источник
Вы также можете пропустить эхо: git log -1 --format = "% ad $ filename"
Кевин Лида,
0

Вот версия ответа Эндрю М для раковин рыб для тех, кто использует рыбу.

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

Я храню это как функцию рыбы для легкого доступа.

Кевин Черепский
источник
0

Для тех из нас, кто использует Windows и PowerShell, ответ Эндрю М, с машиночитаемой настройкой:

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

Пример вывода:

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
Джеймс Скемп
источник