GitのCommit中のAuthor名およびCommitter名を変える

ローカルで持っているGitリポジトリGitHubにpushしてしまいたいなぁ、と思ったのだが、pushする直前にAuthorおよびCommitterとして自分の本名を使っていることに気づいた。そういえば、Gitを使い始めたころはuser.nameに正直に本名を入れていたなぁ…。

そのままでも大した問題はないのだが、ネット上ではidesakuで通すことにしているので、こいつらを修正した。その際、あまり使わないコマンドを使ったので、作業ログなど残してみる。
さて、どうすればよいか。すぐに思いついたのは、git-rebaseを使うことである。

ところで、Gitは全てのコミットにAuthorとCommitterの二つの名前を記録している。これは、オープンソース分野でよくある「パッチを書いた人(Author)と、それをリポジトリにコミットした人(Committer)が違う」ケースに対応するための措置である。*1

git-rebaseだとこのうちCommitterしか変更できない*2。そもそも、git-rebaseでは最初のコミットを変更できない。

…どうしよう?

http://progit.org/book/ch6-4.htmlによると、git-filter-branchを使うと良いらしい。ということで、次のようなコマンドを実行してみた。*3また、名前だけでなくemailも古かったので、ついでに変更した。

$ git filter-branch --commit-filter '
    GIT_AUTHOR_NAME="idesaku"
    GIT_AUTHOR_EMAIL="(メールアドレス)"
    GIT_COMMITTER_NAME="idesaku"
    GIT_COMMITTER_EMAIL="(メールアドレス)"
    git commit-tree "$@"
' HEAD

実行してみたところ、無事変更できた。

--commit-filterの後に、Commitを操作するためのシェルスクリプトを書いている。俺の場合は全てのCommitのAuthorとCommitterを同様に変更すればよいため、これだけシンプルになった。

操作するCommitを選択したい場合、例えば複数人で使用しているリポジトリで、特定の人物によるCommitのみ変更したい、といった場合は、次のように書く必要があるだろう。

$ git filter-branch --commit-filter '
if [ "$GIT_COMMITTER_NAME" = "old_name" ]; then
    GIT_COMMITTER_NAME="new_name"
fi
git commit-tree "$@"
' HEAD

ユーザを特定する条件には、GIT_COMMITTER_NAMEの他にも、例えばGIT_COMMITTER_EMAILを使ってもいいかもしれない。

*1:普通にgit-logを使うとAuthorしか表示されないが、git log --pretty=full とすると、Author, Committer両方の名前がログに表示される。普通にコミットすればAuthor = Committerとなるのだが、git commit --author=AuthorNameとすることで、Authorの名前を指定できる。

*2:やり方を知らないだけかもしれないが。

*3:実行する前にgit-cloneしておくこと。とても危険な操作なので、バックアップ必須。