まとまった情報がなさそうだったので。歴史修正していきましょう 🥺
filter-branch
や rebase
のような歴史修正コマンドは危険なので、バックアップを取るなど安全を確保した上で自己責任での作業をお願いします 🙇
環境
Git v2.36.0
共通の準備
git config --global user.name "Alice"
git config --global user.email alice@example.com
git config --global user.signingkey 0123456789ABCDEF # コミットに署名する場合のみ
git config --global commit.gpgsign true # コミットにGPG署名する場合のみ
歴史修正
いくつかやり方の候補があります。それぞれ実行結果が少しずつ異なるので、状況に合う方法を選択してください。
A. filter-branch 署名あり(全コミット)
git filter-branch -f --commit-filter '
GIT_AUTHOR_NAME="Alice";
GIT_AUTHOR_EMAIL="alice@example.com";
GIT_COMMITTER_NAME="Alice";
GIT_COMMITTER_EMAIL="alice@example.com";
git commit-tree -S "$@";
' HEAD
- 歴史修正前の AuthorDate と CommitDate の両方を維持
- Author と Committer を指定したもので上書き
- filter-branch は何でもできてしまう最強のオプションなので、rebase より気分的にちょっと怖いかも
B. filter-branch 署名なし(全コミット)
git filter-branch -f --env-filter '
GIT_AUTHOR_NAME="Alice";
GIT_AUTHOR_EMAIL="alice@example.com";
GIT_COMMITTER_NAME="Alice";
GIT_COMMITTER_EMAIL="alice@example.com";
' HEAD
- 歴史修正 A の署名なしバージョン
- 歴史修正前のコミットに署名があってもその署名は消える
C. filter-branch 署名あり(条件付き)
git filter-branch -f --commit-filter '
if [ "$GIT_AUTHOR_EMAIL" = "alice@localhost" ];
then
GIT_AUTHOR_NAME="Alice";
GIT_AUTHOR_EMAIL="alice@example.com";
GIT_COMMITTER_NAME="Alice";
GIT_COMMITTER_EMAIL="alice@example.com";
git commit-tree -S "$@";
else
git commit-tree -S "$@";
fi' HEAD
- if の
test
条件に一致するコミットのみ上書き - 署名なしの場合も歴史修正 B と同様の考え方でできると思います
D. rebase & amend author(全コミット)
git rebase -i --root -x 'git commit --amend --author="Alice <alice@example.com>" -C HEAD'
# エディタが起動するので何も編集せずに保存して閉じる
- 歴史修正前の AuthorDate を維持
- Author を指定したもので上書き
- 現在の git config に従って Committer と CommitDate を更新
E. rebase & amend reset-author(全コミット)
git rebase -i --root -x "git commit --amend --reset-author -C HEAD"
# エディタが起動するので何も編集せずに保存して閉じる
- 歴史修正前のメタデータは原則すべて消える
- 現在の git config に従って Author と AuthorDate を更新
- 現在の git config に従って Committer と CommitDate を更新
F. rebase & amend reset-author(一部のコミット)
git rebase -i <上書きしない中で最新のコミットハッシュ> -x "git commit --amend --reset-author -C HEAD"
# エディタが起動するので何も編集せずに保存して閉じる
-
author
オプションを使う場合も同様
備考
- いずれの方法でもオリジナルのコミット署名は消えます。デジタル署名が歴史修正に負けたらまずいので当然ですが
- オプションなしの
$ git log
で表示されるタイムスタンプは AuthorDate ですが、GitHub上で表示されるタイムスタンプは CommitDate です(2022-04-21現在)
確認
git log --pretty=fuller --show-signature
リモートリポジトリへの反映
必要な場合のみ。
git push --force-with-lease [origin] [branch]