開発ツール

git rebase -iでコミット履歴を整理する

読了 7分
開発ツール

git rebase -iでコミット履歴を整理する

作業に集中していると、「とりあえずコミット」「typo修正」「やっぱり戻す」みたいな細かいコミットがどんどん溜まっていきます。あとから自分の履歴を見て、これは人に見せられないな…となったときのメモです。

そのままプッシュするとレビュアーが履歴を追いにくくなるので、プッシュ前に git rebase -i(インタラクティブリベース)で整えておくとよさそうです。

何ができるのか

インタラクティブリベースでは、直近のコミット列に対してこんな編集ができます。

  • コミットメッセージを書き直す(reword)
  • 複数のコミットを1つにまとめる(squash / fixup)
  • コミットの順番を入れ替える
  • 不要なコミットを削除する(drop)
  • 特定のコミットで一旦止めて内容を直す(edit)

意外といろいろできます。これは便利。

まず起動してみる

直近のコミットいくつかを対象にするには、HEAD~N の形で範囲を指定します。たとえば直近3コミットを対象にするなら、以下のようにします。

git rebase -i HEAD~3

するとエディタが開いて、対象コミットが 古い順 に並んだ指示リストが表示されます。こんな感じです。

pick a1b2c3d ログイン機能の骨組みを追加
pick e4f5a6b typo修正
pick c7d8e9f ボタンの色を調整

# Rebase ... onto ...
# Commands:
# p, pick   = コミットをそのまま使う
# r, reword = コミットは使うがメッセージを編集する
# s, squash = 直前のコミットに統合し、メッセージも結合する
# f, fixup  = squashと同様だが、このコミットのメッセージは捨てる
# d, drop   = コミットを削除する

各行の先頭の pick を、やりたい操作のキーワードに書き換えて保存・終了すると、その内容で履歴が組み直されます。最初は並び順が古い順なのを忘れがちなので、ここだけ注意してください。

メッセージを書き直す(reword)

メッセージだけ直したいときは、その行を reword(または r)に変えます。

pick a1b2c3d ログイン機能の骨組みを追加
reword e4f5a6b typo修正
pick c7d8e9f ボタンの色を調整

保存するとメッセージ編集用のエディタが開くので、たとえば「フォームのバリデーションを追加」のように分かりやすい文言へ直します。これで、後から見ても何をしたコミットか分かるようになります。

コミットをまとめる(squash / fixup)

「typo修正」みたいな、独立させる意味のないコミットは、直前のコミットに統合してしまいます。squash は両方のメッセージを結合し、fixup は統合先のメッセージだけ残して、まとめる側のメッセージは捨てます。

pick a1b2c3d ログイン機能の骨組みを追加
fixup e4f5a6b typo修正
pick c7d8e9f ボタンの色を調整

この例では「typo修正」が「ログイン機能の骨組みを追加」に吸収されて、結果として2コミットになります。メッセージを残す必要がない修正コミットは、fixup が手軽でよく使います。

ちなみに、コミット時にあらかじめ git commit --fixup=<対象コミット> で印を付けておいて、git rebase -i --autosquash を使うと、まとめる対象を自動で並べ替えてくれます。慣れてきたらこちらが楽です。

順番の入れ替えと削除

行を上下に並べ替えれば、その順序でコミットが再構成されます。完全に不要なコミットは行ごと消すか、drop を指定します。

pick c7d8e9f ボタンの色を調整
pick a1b2c3d ログイン機能の骨組みを追加
drop e4f5a6b 一時的なデバッグログ

消し忘れたデバッグログをここで drop できるのは地味にありがたいです。

途中で止めて直す(edit)

特定のコミットの内容そのものを直したいときは edit を指定します。そのコミットの状態でリベースが一時停止するので、ファイルを修正して次のように進めます。

# ファイルを編集したあと
git add .
git commit --amend   # そのコミットに変更を取り込む
git rebase --continue

ここは怖いので注意

リベースは履歴を 書き換える 操作です。ここはちょっと怖いところなので、共同作業では次の点に気をつけてください。

  • すでに共有されているブランチの履歴は書き換えないmain や他の人も触っている履歴を変えると、全員に影響します。整えるのは自分の作業ブランチに限定しておきます。
  • リベース後のプッシュは強制プッシュが必要になります。その際は素の --force ではなく --force-with-lease を使うと、自分が知らないうちに進んだ相手のコミットを上書きする事故を防げます。
git push --force-with-lease
  • 操作を間違えても、git reflog で直前の状態を確認して戻せます。慣れるまでは作業前にブランチをコピー(git branch backup)しておくと安心です。これで失敗しても精神的に楽です。

まとめ

  • git rebase -i HEAD~N で直近N件を整理できる
  • reword でメッセージ修正、squash / fixup で統合、drop で削除、edit で内容修正
  • 共有済みの履歴は書き換えない。プッシュは --force-with-lease
  • 失敗しても reflog で戻せる

レビューのしやすさは履歴の読みやすさに直結します。詳しい仕様はGitの公式ドキュメント(git-rebase)も見つつ、まずは自分のブランチで気軽に試してみるとよさそうです。以上です。