なんらかの理由でGitのコミットに入っている日付(タイムスタンプ)をまとめて書き換えたいとします。特定のブランチの日付がまとめて変だ、とかですね。やり方を調べてまとめました。
TL;DR
mainから現在のブランチまでのコミットを全て現在時刻にしたい場合こう書くといいみたいです。
DT=$(date -R); git filter-branch --env-filter "GIT_AUTHOR_DATE='${DT}'; GIT_COMMITTER_DATE='${DT}';" main...HEAD
-
$(date -R)
を書き換えれば現在時刻以外にもできます -
main...HEAD
を書き換えれば任意のリビジョンを選択できます - 何回も流すときは
-f
を付けることになるみたい?
どういう事をやっているスクリプトなのか
おそらくGitに慣れている人にとっては大したことない処理だと思うのですが、要所についてまとめ直してみました。
author dateとcommitter date
Gitの日付にはauthor dateとcommitter dateがあります。多くの場合に目にするのはauthor dateですがcommitter dateも記録されています。
$ git show --pretty=fuller | head -5
commit da9899ed76379b951cb80cdd540e533861c02576
Author: saka1 <github@example.com>
AuthorDate: Mon Aug 16 09:13:17 2021 +0900
Commit: saka1 <github@example.com>
CommitDate: Mon Aug 16 09:13:17 2021 +0900
そもそもauthorとcommitterは何が違うのだろうと思うところです。どうやらGitはその差分を作った人と実際にコミットする人が分離することも想定して作られているようです。『入門Git』 P.13にはこうあります。
多くのオープンソースのプロジェクトでは、プロジェクト参加者がプロジェクトの最新版に対して、パッチ(patch)という形で提案した修正・改良・拡張を、プロジェクトを管理する立場の人に審査し、良いものだけをプロジェクトに取り入れる、という進め方をします(後に、10.1節にて詳述します)。このような作業の流れでは、変更をもともと作成した人と、それを審査して取り入れることを決め、実際にコミットオブジェクトを作成する人とが同一人物でない事は普通に起こります。前者はauthor、後者はcommitterとして記録されます。
したがって日付もまたauthor dateとcommitter dateとして分離しうる、という背景のようでした。
Gitが認識する日付
Gitの公式ドキュメントにはauthor dateとcommitter dateに入れられる日付形式について規定があります。
https://git-scm.com/docs/git-commit/2.32.0#_date_formats
これによると、認識してくれる形式は3つ(Git内部形式、RFC 2822、ISO 8601)あるのですが、ワンライナーではdateコマンドの-R
オプションで生成が容易なRFC 2822形式を使いました。
$ date -R
Mon, 16 Aug 2021 08:41:54 +0900
git filter-branch
filter-branchは危険……とは言うものの今回のようなことをしたい時には頼りになります。多数のオプションがありますが今回の用途では--env-filter
が最適そうでした。
This filter may be used if you only need to modify the environment in which the commit will be performed. Specifically, you might want to rewrite the author/committer name/email/time environment variables (see git-commit-tree[1] for details).
https://git-scm.com/docs/git-filter-branch#Documentation/git-filter-branch.txt---env-filterltcommandgt