なぜ rebase をする?
結論、履歴を直線にして読みやすくし、自分のコミットが「最新の親ブランチの上に載せ替え」られ、同じ内容でも別ハッシュの新コミット列として並び直る(履歴が書き換わる)。
-
履歴をまっすぐ保つ
チームのタイムラインを追いやすくし、レビュー・調査が楽になる。 -
fast-forward マージを可能にする
分岐が解消されるので、git merge --ff-onlyでマージコミット無しに統合できる。 -
小出しに衝突を解消
1コミットずつ最新の親に当て直すので、巨大な一括コンフリクトを避けられる。 -
公開前にコミットを整形
rebase -iでsquash/fixup/rewordして“意味単位”の履歴にまとめられる。
例
main: A --- B --- C
\
feature/login: D --- E
feature/login を最新 main の上に載せ替える:
git checkout feature/login
git fetch origin
git rebase origin/main
結果(D,E が D’,E’ に作り直されて直線化):
main: A --- B --- C
feature/login: D' --- E'
続いて fast-forward で統合:
git checkout main
git merge --ff-only feature/login # マージコミット無しで進む
最終形:
A --- B --- C --- D' --- E' (直線)
git merge との違い
git merge は rebase と目的は似ていますが、やり方と結果がまったく違います。
簡単に言うと、
merge は「実際の履歴をそのまま残す」
rebase は「履歴をきれいに並べ替える」
それぞれの操作が「履歴をどう扱うか」で大きく分かれます。
目的の違い
| 操作 | 目的 |
|---|---|
| git merge | 複数ブランチの変更を「統合」する。履歴を保持する。 |
| git rebase | 自分の変更を「付け替える」。履歴を整理して直線にする。 |
実際にどう違うのか
例の前提
main: A --- B --- C
\
feature/login: D --- E
git merge の場合
git checkout main
git merge feature/login
結果(3ウェイマージ):
A --- B --- C ------- F ← main(マージコミット)
\ /
D --- E ← feature/login
- 新しいマージコミット F が作られる。
- main と feature の変更履歴が両方残る。
- 誰がどこで統合したかが明確。
- ただし履歴が分岐して「グラフが複雑」に見える。
git rebase の場合
git checkout feature/login
git rebase main
結果:
A --- B --- C --- D' --- E' ← feature/login(再作成されたコミット)
-
feature のコミットを main の上に並べ直す。
-
D, E は同じ内容だが別ハッシュ(D', E') になる(履歴書き換え)。
-
その後、main に fast-forward マージできる:
git checkout main git merge --ff-only feature/loginこれで履歴がまっすぐになる。
どう使い分けるか
-
merge
→ 履歴を正確に残したいとき(チーム統合、main/devマージ時)
→ 例:本番リリース前の統合 -
rebase
→ 自分の作業ブランチを最新状態に追従させたいとき
→ 例:pull前の整理、レビュー前の履歴整理、fast-forwardマージをしたいとき
Git rebase のリスクと注意点まとめ
履歴が書き換わる(コミットIDが変わる)
- rebase は「既存のコミットを再適用して新しく作り直す」処理。
- 同じ内容でもコミットID(ハッシュ)がすべて変わる。
- 結果として「別のブランチ」とみなされるため、
他の開発者が古い履歴を基に作業していると衝突が起きる。
強制プッシュ(--force)が必要になる
- 履歴が変わるため、通常の
git pushは拒否される。 -
git push --forceまたはgit push --force-with-leaseが必要。
--force-with-leaseを使うことで、他人の更新を誤って消すのを防げる。
コンフリクトがコミットごとに発生する
- rebase はコミットを1つずつ適用し直すため、
同じファイルを複数のコミットで触っていると、
各ステップでコンフリクトが起きることがある。 - コンフリクトが多い場合は
rebaseよりmergeを選ぶ。 -
git rebase --skip/--abort/--continueの流れを覚えておく。
途中での中断・失敗時の対処を知っておく
rebase 中に失敗しても、怖がらず以下で戻せます。
| 状況 | コマンド | 内容 |
|---|---|---|
| rebase 中止 | git rebase --abort |
開始前に戻す |
| コンフリクト解決後続行 | git rebase --continue |
続行 |
| 現在のコミットをスキップ | git rebase --skip |
今の変更を飛ばす |
| 元の状態に完全復帰 |
git reflog → git reset --hard HEAD@{1}
|
失敗前の状態に戻す |