【Git】rebase -i でコミット履歴を整理する:実務で役立つ5つのパターン
はじめに
みなさん、こんにちは。
開発をしていて、こんな経験はありませんか?
- 「あ、タイポした…
fix typoってコミットしちゃえ」 - 「とりあえず実装途中だけどコミット(WIP)」
- 「ブランチの履歴を見直していたら、消したいコミットがあることに気づいた…」
そんな時に役立つのが git rebase -i です。
今回は、実務で頻出するパターンに絞って、コミット履歴を綺麗に整形する魔法のコマンド git rebase -i の使い方を解説します。
そもそも:Merge と Rebase の違い(超概略)
rebase -i に入る前に、よくある「Merge か Rebase か」論争について、実務的な観点でサクッと整理します。
Git Merge
- 特徴: 歴史を「ありのまま」残す。
- イメージ: 分岐した道が合流地点でつながる。
- メリット: コンフリクト解決の履歴も残るため、追跡性が高い。
Before: マージ前
Mainブランチ(C)とFeatureブランチが分岐しています。
After: マージ後
合流地点に新しいコミット(M)が作られます。枝分かれした歴史が残ります。
Git Rebase
- 特徴: 歴史を「作り変える」。
- イメージ: 分岐した道を、最初から一本道だったかのように付け替える。
- メリット: ログが一直線になり、非常に読みやすくなる。
Before: リベース前
Mergeの時と同じく、ブランチが分岐している状態です。
After: リベース後
Featureブランチの根元を、Mainの最新(C)に付け替えます。歴史が一直線になります。
git rebase -i とは?
interactive(対話的)モードでリベースを行うコマンドです。
過去のコミットに対して、以下のことができます。
- コミットをまとめる (Squash)
- メッセージを書き直す (Reword)
- コミットを削除する (Drop)
- 順番を入れ替える
基本コマンド
直近 N 個のコミットを編集したい場合:
$ git rebase -i HEAD~N
※ N には数字(3や5など)が入ります。
💡 Tips: コミット数を数えるのが面倒な場合
「あれ、何個コミットしたっけ?」といちいち数えるのが手間な場合は、親ブランチを指定するのが便利です。
# mainブランチから分岐した後の、自分のコミット全てを対象にする
$ git rebase -i main
こうすると、「main から現在のブランチまでの差分コミット」がすべてリストアップされます。プルリクエストの作成前など、自分の作業分をまとめて整理したい時に非常に強力です。
実務で使える具体例 5選
では、実際にどう使うのか、よくあるシチュエーション(Case)別に見ましょう。
Case 1: コミットを1つにまとめたい (Squash)
実装中に「一旦保存」として WIP (Work In Progress) コミットを連発してしまった場合。
Before:
pick a1b2c3d 機能Aの実装完了
pick e5f6g7h WIP
pick i8j9k0l WIP
pick m1n2o3p 機能Bの実装完了
これを「機能Bの実装完了」の1つにまとめたいときは、squash (または s) を使います。
Action:
pick a1b2c3d 機能Aの実装完了
pick e5f6g7h WIP
s i8j9k0l WIP # ← 上のコミットにまとめる
s m1n2o3p 機能Bの実装完了 # ← 上のコミットにまとめる
これで、3つのコミットが1つに結合され、コミットメッセージの編集画面が開きます。そこで綺麗なメッセージを書けばOKです。
Case 2: 直前の修正を取り込みたい (Fixup)
「コミットした直後にタイポを見つけた!履歴を汚さずに直したい!」
そんな時は squash よりも fixup (または f) が便利です。
Before:
pick a1b2c3d ログイン機能の実装
pick e5f6g7h fix: typo修正
Action:
pick a1b2c3d ログイン機能の実装
f e5f6g7h fix: typo修正 # ← ログを残さずに上のコミットに融合
Case 3: コミットメッセージを書き直したい (Reword)
「機能実装」とだけ書いたけど、後から「ユーザー登録APIの実装」と具体的に書きたくなった場合。
Action:
r a1b2c3d 機能実装 # ← pick を reword (r) に変える
保存するとエディタが立ち上がり、メッセージだけを修正できます。
Case 4: 間違ったコミットを消したい (Drop)
誤って console.log だらけのコミットや、不要なファイルを含めてしまった場合。
Action:
pick a1b2c3d 必要なコミット
d e5f6g7h 不要なコミット # ← pick を drop (d) に変える
pick i9j8k7l 次のコミット
これだけで、そのコミットは歴史から抹消されます。
Case 5: コミットの順番を変えたい
機能Aと機能Bの依存関係がない場合、単純に行を入れ替えるだけで履歴の順番が変わります。
Action:
pick m1n2o3p 機能B # ← 行を入れ替えるだけ
pick a1b2c3d 機能A
Result: ログ上では「機能B」→「機能A」の順になります。
コマンド一覧のカンペ
| コマンド | ショートカット | 説明 |
|---|---|---|
pick |
p |
コミットをそのまま使う |
reword |
r |
コミットメッセージを変更する |
squash |
s |
直前のコミットと結合する(ログ編集あり) |
fixup |
f |
直前のコミットと結合する(ログ編集なし・破棄) |
drop |
d |
コミットを削除する |
⚠️ 原則禁止(必要ならチーム内で合意の上)
rebase は「歴史を改変する」行為です。
もしあなたが origin/main をリベースして push -f してしまうと、他のメンバーの手元にある歴史と矛盾が生じ、チーム全体が大混乱に陥ります。
Rebaseしていいのは、「まだPushしていない」、あるいは「自分しか触っていない(PR作成中の)」ブランチだけ と覚えておきましょう。
まとめ
git rebase -i を使いこなすと、開発効率とコードの品質がグッと上がります。
- 作業中は自由にコミット(WIP歓迎!)
- Pull Request を出す前に
rebase -iで整形 - レビュワーに優しい「綺麗な履歴」を提出
まずは個人の練習用ブランチで squash や fixup から試してみてください。「履歴を操れる」感覚を掴めると、Gitがもっと楽しくなりますよ!
Discussion