鯨飲馬食

いろいろつまみ食いで勉強したことのメモ書き

Gitで管理されたファイルの更新時刻の2つの定義

ファイルの更新時刻とは何か?単にディレクトリツリー内のファイルの話をしているなら、そのファイルが最後に変更された時刻という定義ができる。ls -l 対象ファイル で表示されるファイルのタイムスタンプ、いわゆるmtimeである。

一方、Gitで履歴管理されているファイルを対象とした場合、ファイルの更新時刻について、

  • カレントブランチにそのファイルの内容が反映された時刻
  • ファイルの内容が最後に変更された時刻

という2つの定義が存在する。*1

前者は

git log -1 --pretty=fuller --show-pulls -- 対象ファイル

で表示されるCommitDateで、カレントブランチに注目して、そのファイルの変更がカレントブランチに取り込まれたタイミングを示す。後者は

git log -1 --pretty=fuller -- 対象ファイル

で表示されるCommitDateで、ファイルの内容の変更に注目して、(カレントブランチに取り込み済みの)ファイルの変更が実際に行われたタイミングを示す。*2

一本のブランチのみで開発を行っている場合は両者は同じ時刻を示すが、ブランチとマージを使った開発をしている場合には一般にそれぞれが異なる時刻を示す。

これらはどちらも「ファイルの更新時刻」であり、「Gitで管理されたファイルの更新時刻とは何か?」という答えが一つじゃない問いを見つけて面白いなと思った。*3

このことに気づいたのは、gitの作業ツリー内のファイルのタイムスタンプを「ファイルがコミットされた時刻」に合わせてくれる2つのツール

で、ファイルの更新時刻を決めるのに git log -m –name-only するか git log –name-only するかの違いの考察から。

*1:コミットに付随するAuthorDateとCommitDateという2つのタイムスタンプが別々の時刻を表す場合もあるが、この記事ではその話題は扱わない。

*2:似た話は git blame の --first-parent ありなしでも現れる。そちらはファイル内の各行の更新タイミングの話だが、 --first-parent ありの場合は変更をカレントブランチに取り込んだコミット、なしの場合は変更を行ったコミットが提示される。

*3:ブランチを使った開発の目的が、変更と統合を分離するためだったことを思い出すと、2つの更新時刻が現れるのは当たり前と言えば当たり前なのだけど。