git rebase -i
git rebase -i
の実行の際に squash
やその省略形である s
を指定すると、図のように複数のコミットを1つにまとめることが出来ます。
git rebase -i develop
pick abcd123 すごい機能 仮実装
- pick efgh456 バグ修正
- pick ijkl789 誤字修正
+ squash efgh456 バグ修正
+ squash ijkl789 誤字修正
If you want to fold two or more commits into one, replace the command "pick" for the second and subsequent commits with "squash" or "fixup".
しかし、git rebase -i
するたびに手作業で全ての pick
を s
に置換していくのは面倒ですし、 :%s/pick/s/gc
と入力して一気に置換するのもそれはそれで面倒ですよね。
squash を2個のコマンドで
代わりに以下のコマンドで同様の処理が実行できます。
git reset --soft <base-branch>
git commit -m <commit message>
例えば、具体的には以下のようになります。
git reset --soft develop
git commit -m "すごい機能を実装"
※これを行うとコミットメッセージ、コミット時刻、コミットの author が消失してしまうため注意してください。
※また、ステージング済みの変更があるとそれもコミットされてしまうため注意してください。
解説
--soft
を指定して git reset
を行うことにより、コミット済みのファイルをインデックスに残したまま、<base-branch>
ブランチまでのコミット履歴を一旦無かったことにしています。(つまり、現在チェックアウトしているブランチの指し示す先が、<base-branch>
の指し示すコミットと同じになります。)
この状態で git commit
を行うことで、インデックスに追加されているファイルが再度コミットされ、1つだけのコミットが残ることになります。
参考リンク(余談)
この記事を書いた後に気付いたのですが、世の中には賢い人が居るようで……。
EDITOR="sed -i '2,/^$/s/^pick\b/s/'" git rebase -i <ref>
余談の解説
git rebase コマンドは EDITOR で指定されたエディタを開き、引数として一時ファイルを渡しています。EDITOR に指定されたコマンドでは、指定されたファイルの 2
行目から /^$/
行目まで /^pick\b/
を s
に置換する(s
コマンド)という処理を行い、指定されたファイルに上書きします。 /^$/
行目という正規表現に一致する行は存在しないので、最後までの全ての行に対して処理が行われることになります。
ただし、git config core.editor
などで既に他のエディタが設定されている場合は、EDITOR 環境変数よりもそちらの設定の方が優先されてしまうようでした。
お詫び
git squash
というコマンドはありません。記事のタイトルは釣りです。