24.

Git rebase 完全ガイド (インタラクティブ/コンフリクト)

編集
この記事の要点
  • git rebase main は現在のブランチのコミットを main の最新の上に積み直す。履歴が直線化
  • merge との違い: merge = マージコミット作成 / 履歴が分岐したままrebase = 直線 / マージコミット無し
  • git rebase -i HEAD~3 でインタラクティブ。pick / squash / fixup / reword / edit / drop でコミット編集
  • コンフリクト発生時: 解決 → git addgit rebase --continue、やめるなら --abort、スキップは --skip
  • リベース後の push は履歴書き換えのため git push --force-with-lease共有ブランチでの 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 との違い

項目mergerebase
履歴の形分岐したまま、マージコミット追加直線化、マージコミット無し
コミット 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 ", 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                    develop
git 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~5pickreword に置換するか、git commit --amend(直近のみ)。

関連

  • git merge — rebase の対義操作
  • git cherry-pick — 特定コミットだけ別ブランチに適用
  • git reflog — rebase 取り消しに必須
  • git pull --rebase — pull で自動 rebase
編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 用語一覧
  2. エラー一覧
  3. git本体のインストール(Linux)
  4. Linuxサーバーへのgit導入とクライアントのセットアップ
  5. リモートリポジトリをローカルリポジトリとしてクローンする方法
  6. リモートとローカルのリポジトリを同期(pull)する方法
  7. 設定の確認
  8. gitユーザー名とemailの設定
  9. リモートリポジトリの作成
  10. ローカルリポジトリの作成
  11. 新規ファイル/ディレクトリをインデックスに登録
  12. インデックスの登録状態を確認
  13. ローカルリポジトリの変更をコミット
  14. コミット履歴の確認
  15. クライアントからリモートリポジトリの接続設定、確認、削除
  16. リポジトリへのプッシュ
  17. リモートリポジトリからクライアントへのSSHクローン
  18. リモートとローカルの差分表示
  19. バージョンの確認
  20. プロキシの設定
  21. ローカルをリモートリポジトリの状態に戻す
  22. ブランチの作成, 一覧表示, 切り替え
  23. ブランチのマージと削除
  24. リベース
  25. .gitignoreの書き方
  26. .gitignoreの設定が反映されない場合
  27. 特定のファイルをgitの管理から外す方法
  28. 参照(ORIG_HEAD, HEAD, FETCH_HEAD)
  29. git rm [-r --cached] の取り消し
  30. 一部のディレクトリ/ファイルのみをリポジトリから復元する方法
  31. ローカルとリモートリポジトリの有無を同期
  32. pushの取消し方法
  33. マージツールの起動方法
  34. Gitで「MERGING」の状態