🙆‍♀️

【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(対話的)モードでリベースを行うコマンドです。
過去のコミットに対して、以下のことができます。

  1. コミットをまとめる (Squash)
  2. メッセージを書き直す (Reword)
  3. コミットを削除する (Drop)
  4. 順番を入れ替える

基本コマンド

直近 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:

vim
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:

vim
pick a1b2c3d ログイン機能の実装
f e5f6g7h fix: typo修正  # ← ログを残さずに上のコミットに融合

Case 3: コミットメッセージを書き直したい (Reword)

「機能実装」とだけ書いたけど、後から「ユーザー登録APIの実装」と具体的に書きたくなった場合。

Action:

vim
r a1b2c3d 機能実装  # ← pick を reword (r) に変える

保存するとエディタが立ち上がり、メッセージだけを修正できます。

Case 4: 間違ったコミットを消したい (Drop)

誤って console.log だらけのコミットや、不要なファイルを含めてしまった場合。

Action:

vim
pick a1b2c3d 必要なコミット
d    e5f6g7h 不要なコミット  # ← pick を drop (d) に変える
pick i9j8k7l 次のコミット

これだけで、そのコミットは歴史から抹消されます。

Case 5: コミットの順番を変えたい

機能Aと機能Bの依存関係がない場合、単純に行を入れ替えるだけで履歴の順番が変わります。

Action:

vim
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 を使いこなすと、開発効率とコードの品質がグッと上がります。

  1. 作業中は自由にコミット(WIP歓迎!)
  2. Pull Request を出す前に rebase -i で整形
  3. レビュワーに優しい「綺麗な履歴」を提出

まずは個人の練習用ブランチで squash や fixup から試してみてください。「履歴を操れる」感覚を掴めると、Gitがもっと楽しくなりますよ!


参考リンク

Sun* Developers

Discussion