ガイド

cherry-pick と rebase の実践テクニック

コミットの整理・移動・救済など、日常的に使える実践パターン集

cherry-pick と rebase の実践テクニック diagram

前提

  • rebase と cherry-pick はコミットハッシュが変わる操作

    プッシュ済みのコミットに対して実行すると force push が必要になり、チームメンバーの履歴と不整合を起こします。

  • このページのテクニックは未プッシュのコミットが前提

    まだプッシュしていないローカルのコミットに対して使うことを想定しています。

  • 多くの場面では merge だけで十分

    詳しくは きれいな履歴にこだわりすぎない を参照してください。

interactive rebase でコミットを整理する

git rebase -i では、エディタで各コミットに対して以下のコマンドを指定できます。

コマンド 意味
pick そのまま使う
reword メッセージのみ変更
squash 前のコミットと統合してメッセージを編集
fixup 前のコミットと統合してメッセージは破棄
drop コミットを削除

PR前にコミットを整理するのが定番の使い方です。

fixup! プレフィックス付きコミットと --autosquash を組み合わせると、自動で対象コミットの直後に配置されるので効率的です。

bash
# PR前にコミットを整理する
git rebase -i origin/main
# エディタで pick/squash/fixup/reword/drop を指定

# fixup コミットを作る → 後で自動整理
git commit --fixup=abc1234
git rebase -i --autosquash origin/main

# 直近5コミットを整理
git rebase -i HEAD~5

間違ったブランチにコミットした場合の救済

  1. 間違ったコミットのハッシュをメモ

    git log --oneline で対象のコミットハッシュを確認してメモしておきます。作業中に位置がずれても戻せるように、必ず最初に記録します。

  2. 正しいブランチに移動して cherry-pick

    git switch で目的のブランチに切り替え、git cherry-pick <hash> でコミットを取り込みます。複数コミットなら git cherry-pick A..B の範囲指定も使えます。

  3. 元のブランチから reset でコミットを消す

    元のブランチに戻り、git reset --hard HEAD~N で不要なコミットを削除します。既にプッシュ済みの場合は影響があるため、git revert を検討してください。

bash
# 1. まず間違ったコミットのハッシュを確認
git log --oneline -3
# abc1234 間違えてmainにコミットした変更

# 2. 正しいブランチに移動してcherry-pick
git switch feature/correct-branch
git cherry-pick abc1234

# 3. 元のブランチからコミットを消す
git switch main
git reset --hard HEAD~1

# 複数コミットを一括で移す
git switch feature/correct-branch
git cherry-pick abc1234..def5678

リリースブランチへのホットフィックス適用

本番で見つかったバグを修正してリリースブランチにも反映するパターンです。

hotfix ブランチを作り、修正後に main とリリースブランチの両方に merge するのが安全です。

cherry-pick でも同じことはできますが、ハッシュが変わるため merge のほうがトラブルが少なくなります。

bash
# hotfix ブランチを作成して修正
git switch -c hotfix/login-npe main
git commit -m "fix: ログイン時のNPEを修正"

# main にマージ
git switch main
git merge hotfix/login-npe

# リリースブランチにもマージ
git switch release/v2.0
git merge hotfix/login-npe

# 不要になった hotfix ブランチを削除
git branch -d hotfix/login-npe

rebase --onto で特定範囲を付け替え

feature/api から分岐した feature/api-test を、main に直接付け替えたい場合に rebase --onto を使います。

構文は git rebase --onto <新しいベース> <古いベース> <対象ブランチ> です。

feature/api の変更を含めずに feature/api-test のコミットだけを main に移せます。

ブランチの依存関係を変更したいときに重宝します。

bash
# feature/api-test を main に直接付け替え
# (feature/api の変更は含めない)
git rebase --onto main feature/api feature/api-test

# 特定範囲のコミットを別ブランチに移す
git rebase --onto main HEAD~3 feature/new

コンフリクト対処の実践

  1. 対象ファイルを修正して git add

    エディタでコンフリクトマーカー(<<<<<<< ======= >>>>>>>)を解消し、修正後のファイルをステージングします。

  2. --continue で再開

    git rebase --continue または git cherry-pick --continue で次のコミットに進みます。残りのコミットでも同じ手順を繰り返します。

  3. どうしても解決できないときは --abort

    git rebase --abort / git cherry-pick --abort で操作前の状態に安全に戻れます。

  4. 繰り返すコンフリクトには rerere を有効化

    git config --global rerere.enabled true で一度解決したコンフリクトが記録され、次回以降自動で再適用されます。

bash
# コンフリクト発生時の基本手順
git rebase origin/main
# CONFLICT が発生

# 1. ファイルを修正して add
git add src/app.ts

# 2. rebase を続行
git rebase --continue

# 諦めて撤退する場合
git rebase --abort

# rerere を有効にしてコンフリクト解決を記憶させる
git config --global rerere.enabled true

関連コマンド