読者です 読者をやめる 読者になる 読者になる

ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Git のコミットのタイムスタンプには author date と committer date の 2 種類があるという話

Git

普段から git rebasegit commit --amend をよく使っており、それらのコマンドはコミットのタイムスタンプを変更しないものだと思っていたのですが、実はコミットのタイムスタンプを変更していることに気付いて驚いたという話。

Git のコミットがもつ 2 種類のタイムスタンプ

特に何もオプションを付けずに git log すると、以下のように Author と Date が表示されます。

$ git log
commit d447eeeb49d04e79b257e7abe6e633541d5e1c52
Author: nobuoka <...@...>
Date:   Thu Jan 31 20:45:47 2013 +0900

    Prepare test tools (mocha and qunit)

で、git rebasegit commit --amend で過去のコミットを変更しても、git log で表示される Date の時刻は変わらないので、コミットのタイムスタンプは変わっていないのだと思っていました。 しかし、1 ヶ月ぐらい前のコミットたちを rebase して GitHub に push したときに、GitHub 上の Network 図では rebase した日時にコミットしたことになることに気付きました。

コミットのタイムスタンプは変わってないはずなのになんでだろうなー、って思って調べてみたら、コミットにはコミットの著者である author とコミットを取り込んだ人を表す committer の 2 つの属性が存在していて、それぞれ別のタイムスタンプ (author date と committer date) を持っている ことがわかりました。 オプションなしの git log で表示されるタイムスタンプは author date であり、git rebasegit commit --amend したときに author date は変更されないが committer date は変更される、ということのようです。 そして、GitHub の Network 図上に表示されるときに参照されるのは committer date なので、git log で表示される時刻と Network 図上の日時がずれる可能性がある、と。

Committer date の表示

通常の git log では表示されない committer date ですが、オプション引数を渡せば表示されます。 例えば --pretty=fuller というオプションを渡すと、以下のような形式で表示されます。

$ git log --pretty=fuller
commit 42c531acc210db031c2d8e82810478e0d8a927cb
Author:     nobuoka <...@...>
AuthorDate: Wed Jan 30 23:50:57 2013 +0900
Commit:     nobuoka <...@...>
CommitDate: Wed Jan 30 23:50:57 2013 +0900

    Make `BasePromise.is` method of module private function

他の表示形式もありますし、git log 以外のコマンドでも committer date を表示させる方法はあります。 詳細は Git のヘルプをご覧ください。

タイムスタンプの書き換え

git rebasegit commit --amend した場合に committer date が変更されるのはある意味では便利ですが、一方で committer date を変更してほしくない場面もままあります。 git rebase を実行した際に、committer date を author date と同じ値にするオプションとして、--committer-date-is-author-date というものがあります。 Author date と committer date を同一にしたい場合はこれを使用するのが一番便利だと思います。

$ git rebase --committer-date-is-author-date <branch>

逆に、git-rebase の際に author date を committer date と同じ値にしたいという場合は、--ignore-date というオプションを使うと便利そうです。

$ git rebase --ignore-date <branch>

詳しくは git のマニュアルをご覧ください。

また、環境変数 GIT_AUTHOR_DATEGIT_COMMITTER_DATE を指定することでコミット時に時刻をその値にすることもできます。 普通に rebase する場合などは必要ないと思いますが、マージコミットを別の親で作り直すときに時刻を昔のものにしたい、というような場合には使えるのではないでしょうか。