hnwの日記

初回のコミットをgit rebaseで修正する方法

gitを使っていると、直前の数commitを1コミットにまとめたくなることがあります。そんなときは「git rebase -i」が便利です。

$ git log --pretty=oneline
dc561dbe3e149310246384a64ea816c46514ce1b Modified 3
bd271250523c06c1e5fe325c8347aa8fb7509692 Modified 2
313003363efef2e9e8179ee322f0403d1cc9944f Modified
5946ef0345ce4c81f93957126bf079db18df604a Initial commit


たとえば上の状況で直前の3個を1コミットにまとめたい場合は、git rebase -iで整理することができます。

$ git rebase -i HEAD~3 # 2コミット目3コミット目をsquashにする
[detached HEAD 105ea02] Support ARM/Linux
 1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.
$ git log --pretty=oneline
105ea02cc6a75c624cf24570aacc8597d7432f34 Support ARM/Linux
5946ef0345ce4c81f93957126bf079db18df604a Initial commit


やった!最悪なcommitだったのが多少マシになりました。


ところで、最初のcommitを含むような修正をしたいときに上記コマンドは使えません。実際試してみると次のように怒られます。

$ git rebase -i HEAD~2
fatal: Needed a single revision
invalid upstream HEAD~2


HEAD~2(HEADの2個前のコミット)なんて無いよね、と怒られています。そもそもgit rebaseは修正したいコミットの親コミットを指定するスタイルなのですが、最初のコミットには親コミットが無いので指定できないというわけです。なんてこった。


こんなときは「git rebase -i --root」で対応できます。

$ git rebase -i --root # 普段のgit rebase -iと同じように使えます
[detached HEAD ae1e3a9] Initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 foo
Successfully rebased and updated refs/heads/master.
$ git log --pretty=oneline
ae1e3a9adea0278fd153d44ce52854f81b87254d Initial commit


最初4コミットあったのが1コミットにまとめられました。歴史の書き換えって素晴らしい!*1


もっとも、1コミット目からしくじったような場合はリポジトリごと作り直す方が素直かもしれませんね。


参考:rebase - Squash all Git commits into a single commit - Stack Overflow

*1:用法・用量を守って正しくお使いください