git で pushしてしまったコミットの authorとcomitterの名前・emailを変更する

はじめに

GitHub, GitLabを使う環境で名前やemailアドレスを使い分けているのだが、これをうっかり間違えてしまった。

間違えるとどうなるかと言うとコミットのAuthor, Comitterの名前に意図しないものが記載されてしまう。これを修正するメモ。

基本的にGitのcommitの名前やメールアドレスを過去からまとめて変更するに書いてあるままである。

ローカルブランチを修正する

#!/bin/sh

git filter-branch --force --env-filter '
        # GIT_AUTHOR_NAMEの修正
        if [ "$GIT_AUTHOR_NAME" = "間違えた名前" ];
        then
                GIT_AUTHOR_NAME="正しい名前";
        fi
        # GIT_AUTHOR_EMAILの修正
        if [ "$GIT_AUTHOR_EMAIL" = "間違えたemail address" ];
        then
                GIT_AUTHOR_EMAIL="正しいemail address";
        fi
        # GIT_COMMITTER_NAMEの修正
        if [ "$GIT_COMMITTER_NAME" = "間違えた名前" ];
        then
                GIT_COMMITTER_NAME="正しい名前";
        fi
        # GIT_COMMITTER_EMAILの修正
        if [ "$GIT_COMMITTER_EMAIL" = "間違えたemail address" ];
        then
                GIT_COMMITTER_EMAIL="正しいemail address";
        fi
        ' -- --all

これをmodify-commit.shのような名前でファイルに保存して、実行する。

このままだとローカルのコミットのみが修正された状態である。

Cannot rewrite branches: You have unstaged changes. が出る場合

git stash save

してから上のコマンドを実行して

git stash pop

すれば出来る場合があった。

状態を確認する

git log --all --pretty=full --graph

この状態だと間違えた名前やemail addressの痕跡はローカルには残っている。

これを消し去っておく:

git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d

この状態で確認すると

git log --all --pretty=full --graph

間違えた名前やemail addressの痕跡は無くなっている。

リモートブランチに反映させる

git push -all --force origin

GitLabでブランチをプロテクトしていると、forceを受け付けない場合がある(forceを許す設定も可能)。

forceを許容させるか、一旦プロテクトを外してから上記コマンドを実行する。 その後プロテクトすれば良い。

ローカルでの痕跡を抹消する

reflogの削除

上記の歴史修正の履歴すらも消す場合は以下のコマンドを実行する:

git reflog expire --expire=now --all

git オブジェクトの削除

git gc --prune=now