タイトル: リベース
SEOタイトル: Git rebase 完全ガイド (インタラクティブ/コンフリクト)
| この記事の要点 |
|
rebase とは
Git の rebase(リベース)は、ブランチのコミットを別の基点(base)に付け替える操作です。日本語では「土台を置き換える」のニュアンス。
[before]
A---B---C feature
/
D---E---F---G main
git rebase main をすると…
[after]
A'---B'---C' feature(B', C' は新しいコミット)
/
D---E---F---G main
feature のコミット A, B, C を main の先端 G の上に積み直す。
歴史が直線になる。
merge との違い
| 項目 | merge | rebase |
|---|---|---|
| 履歴の形 | 分岐したまま、マージコミット追加 | 直線化、マージコミット無し |
| コミット SHA | そのまま保持 | ★ 書き換わる(A → A') |
| push 方法 | 普通の git push | --force-with-lease が必要 |
| 共有ブランチ | OK | ★ 禁止(他人の履歴を破壊) |
| 履歴の見やすさ | 分岐が分かる | 線形で読みやすい |
| コンフリクト解決 | 1 回 | コミット単位で複数回の可能性 |
基本: 他ブランチの上に積み直す
# feature ブランチで作業中、main が進んだので追従したい
git checkout feature
git fetch origin
git rebase origin/main
# ローカル main が最新なら
git rebase main
# pull の代わりに rebase で取り込み
git pull --rebase origin main
# git config で常時 rebase 動作にする
git config --global pull.rebase true
インタラクティブ rebase(神機能)
git rebase -i は、直近のコミットを編集・並べ替え・統合できる強力な機能です。Pull Request 前に履歴を綺麗にするのに使います:
# 直近 3 コミットをインタラクティブに編集
git rebase -i HEAD~3
# 特定コミット以降を編集
git rebase -i abc1234
# main 以降の自分のコミット全部を編集
git rebase -i main
エディタが開き、対象コミット一覧が表示されます:
pick a1b2c3d Add login form
pick e4f5g6h Fix typo in login form
pick i7j8k9l Add password validation
# Rebase 7d8e9f0..i7j8k9l onto 7d8e9f0
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like squash, but discard this commit's message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
# b, break = stop here
# l, label = label current HEAD with a name
# r, reset = reset HEAD to a label
squash / fixup でコミットを統合
# typo fix を前のコミットに統合したい
pick a1b2c3d Add login form
fixup e4f5g6h Fix typo in login form ← f に変更(メッセージは捨てる)
pick i7j8k9l Add password validation
# 保存して終了 → 自動で統合される
# 履歴は 2 コミットに
# squash の場合はメッセージ編集画面が出る
pick a1b2c3d Add login form
squash e4f5g6h Fix typo in login form
pick i7j8k9l Add password validation
reword でメッセージ修正
pick a1b2c3d Add login form
reword e4f5g6h fxi tyop ← r に変更
pick i7j8k9l Add password validation
# 保存後、e4f5g6h のコミットメッセージ編集画面が開く
# → "Fix typo" に修正して保存
drop で不要コミット削除
pick a1b2c3d Add login form
drop e4f5g6h WIP: debug print ← d に変更(行ごと消しても可)
pick i7j8k9l Add password validation
並べ替え
単純に行の順序を入れ替えれば、コミット順が変わります(コンフリクトの可能性あり)。
コンフリクトが発生したとき
$ git rebase main
Auto-merging src/login.php
CONFLICT (content): Merge conflict in src/login.php
error: could not apply a1b2c3d... Add login form
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".# 1. コンフリクトファイルを確認
git status
# 2. ファイルを開いて <<<<<<< ======= >>>>>>> マーカーを編集
# どちらの変更を残すか決めてマーカー削除
# 3. 解決済としてマーク
git add src/login.php
# 4. rebase 継続
git rebase --continue
# 別の対処
git rebase --skip # このコミットを諦めてスキップ
git rebase --abort # rebase 全体をキャンセル、開始前の状態に戻す
rebase 後の push
rebase によりコミットの SHA が書き換わったため、通常の push は拒否されます:
$ git push
! [rejected] feature -> feature (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart.# 強制 push(履歴を上書き)
git push --force-with-lease
# ❌ 危険な --force(他人の push を破壊する可能性)
git push --force # 使うな
# ✅ --force-with-lease は「リモート側に予期せぬ変更がないか」確認する
git push --force-with-lease
共有ブランチでの rebase は禁止
main や develop など他人が pull している共有ブランチを rebase してはいけません。コミット SHA が書き換わると、他人のローカルとリモートが不整合になり、複雑な復旧作業が必要になります。
| ブランチ | rebase 可否 |
|---|---|
| main / master / develop | ❌ 禁止 |
| 共有 feature ブランチ | ⚠ チーム合意必須 |
| 自分専用の feature ブランチ | ✅ OK |
| PR 前の自分の topic ブランチ | ✅ 推奨(整理) |
rebase --onto: 任意の基点に付け替え
# feature を main から develop の上に付け替え
[before]
A---B---C feature
/
--- main ---
\
D---E develop
# git rebase --onto develop main feature
[after]
A'---B'---C' feature
/
--- main ---
\
D---E developgit checkout feature
git rebase --onto develop main feature
# = (main から派生した) feature を develop の上に再構築
# 「直近 2 コミットだけ別ブランチに移したい」
git rebase --onto main feature~2 feature
rebase をやり直したい
# rebase 開始前に戻る(実行中の場合)
git rebase --abort
# rebase してしまった後で取り消したい
git reflog # 過去の HEAD 位置を確認
git reset --hard HEAD@{5} # rebase 前の状態に戻す
FAQ
Q: いつ rebase でいつ merge?
A: 個人ブランチを最新 main 追従には rebase、feature を main に取り込む(PR マージ)には merge or squash merge。GitHub の PR 設定で Rebase and merge / Squash and merge も選べる。
Q: rebase 中に間違って git pull してしまった
A: 二重 rebase で履歴が複雑化。git rebase --abort で開始前に戻ってやり直し。
Q: 大量のコンフリクトが出る
A: git rerere(reuse recorded resolution)を有効化すると、同じコンフリクトを再度解決する手間を省ける。git config --global rerere.enabled true
Q: コミットメッセージだけまとめて修正したい
A: git rebase -i HEAD~5 で pick を reword に置換するか、git commit --amend(直近のみ)。
関連
- git merge — rebase の対義操作
- git cherry-pick — 特定コミットだけ別ブランチに適用
- git reflog — rebase 取り消しに必須
- git pull --rebase — pull で自動 rebase