Como recuperar a data da última modificação de todos os arquivos em um repositório git

64

Eu sei como recuperar a data da última modificação de um único arquivo em um repositório git:

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

Existe uma maneira simples e eficiente de fazer o mesmo para todos os arquivos atualmente presentes no repositório?

Eric Bréchemier
fonte

Respostas:

74

Uma resposta simples seria percorrer cada arquivo e exibir seu tempo de modificação, ou seja:

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

Isso produzirá saída da seguinte forma:

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

Obviamente, você pode controlar isso, já que é apenas um script do bash neste momento - fique à vontade para personalizar o conteúdo do seu coração!

Andrew M.
fonte
2
Eu esperava que houvesse uma opção para obter uma saída combinada em uma única execução do git log, mas sua resposta é melhor do que a que eu tinha em mente usando o find. Eu não conhecia o git-ls-tree, que tem a vantagem de listar apenas os arquivos armazenados no repositório, pulando a pasta .git e os arquivos ignorados. Obrigado.
Eric Bréchemier
Não tem problema, Eric; você está seguindo a mesma rota que eu segui - ou seja, fazendo uma busca e ignorando o diretório .git! :) Pode haver algumas opções usando os comandos git plumbing, mas, francamente, isso funciona muito bem. Se você pudesse encontrar uma maneira de obter as informações por arquivo de uma só vez, isso funcionaria melhor - mas lembre-se, o git opera no estado de consolidação, não no estado de arquivos individuais.
Andrew M.
11
Eu recomendo usar o --format = "% ai" se você desejar carimbos de data e hora ordenáveis ​​em vez de datas legíveis por humanos.
21430 ThorSummoner
2
Desde "cabeça" é apenas uma referência, você pode usar qualquer referência que você quer, seja ele uma tag, ramo, cometer haxixe, etc ..
Andrew M.
11
como disse @ThorSummoner, use% formato ai para a data, e depois é só tubo para classificar para classificar os 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

Essa abordagem também trabalha com nomes de arquivos que contêm espaços:

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

Exemplo de saída:

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

A saída pode ser classificada pelo carimbo de data / hora da modificação, adicionando | sortao final:

git ls-files -z | xargs -0 -n1 -I{} -- git log -1 --format="%ai {}" {} | sort
William Entriken
fonte
Alguma maneira de classificar isso por carimbo de data / hora de modificação?
Amelio Vazquez-Reina
11
@ AmelioVazquez-Reina: Basta adicionar `| sort` até o final do comando.
dotancohen
2
Isso funciona, mas leva um tempo loooong ...
Guillochon
5

Este é um pequeno ajuste na resposta de Andrew M. (Não pude comentar sua resposta.)

Coloque o primeiro nome do arquivo $ entre aspas duplas , para suportar nomes de arquivos com espaços incorporados.

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

Saída de amostra:

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

Agradeço que a solução de Andrew (baseada em ls-tree ) funcione com repositórios simples! (Isso não se aplica a soluções que usam ls-files.)

Kevin G.
fonte
Você também pode pular o eco: git log -1 --format = "% ad $ filename"
Kevin Lyda
0

Aqui está a versão da casca do peixe da resposta de Andrew M, para aqueles que usam peixe.

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

Eu guardo isso como uma função de peixe para facilitar o acesso.

Kevin Cherepski
fonte
0

Para aqueles de nós que usam Windows e PowerShell, a resposta de Andrew M, com o ajuste legível por computador:

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

Exemplo de saída:

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
fonte