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ログの1回の実行で結合出力を取得するオプションがあることを望んでいましたが、あなたの答えは、findを使用して考えていたものよりも優れています。git-ls-treeを知りませんでした。これには、リポジトリに保存されているファイルのみを一覧表示し、.gitフォルダーをスキップしてファイルを無視するという利点があります。ありがとう。
エリックブレケミエ

エリック、問題ありません。あなたは私がやったのと同じルートをたどっています-つまり、.gitディレクトリを見つけて無視します!:) git plumbingコマンドを使用するオプションがあるかもしれませんが、率直に言って、これはかなりうまく機能します。一度にファイルごとに情報を取得する方法を見つけることができれば、それが最適に機能しますが、gitは個々のファイルの状態ではなく、コミットの状態で動作することを忘れないでください。
アンドリューM.

11
人間が読める日付の代わりにソート可能なタイムスタンプが必要な場合は、--format = "%ai"を使用することをお勧めします。
ThorSummoner

2
「HEAD」は単なる参照であるため、タグ、ブランチ、コミットハッシュなど、任意の参照を使用できます。
Andrew M.

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: `| コマンドの最後に並べ替えます。
-dotancohen

2
これは...動作しますが、loooong時間がかかる
Guillochon

5

これはAndrew M.の回答の小さな調整です。(彼の答えにコメントすることはできませんでした。)

スペースが埋め込まれたファイル名をサポートするために、最初の$ 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

Andrewのソリューション(ls-treeに基づく)が裸のリポジトリで動作することを感謝します!(これは、lsファイルを使用するソリューションには当てはまりません。)


gitのログ-1 --format =「%の広告$ファイル名」:あなたはまた、エコースキップすることができます
ケビン・リダ

0

これは、魚を使用する人のためのAndrew Mの答えの魚殻バージョンです。

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を使用している私たちにとって、Andrew Mの答えは、コンピューターが読み取り可能な微調整を加えたものです。

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.