開発ブランチで修正したバグを、今すぐ本番ブランチに反映したい。でもブランチ全体をマージするのは時期尚早だし、他の未完成な変更まで取り込みたくない。そんな場面に遭遇したことはないでしょうか。
git cherry-pickは、まさにこのような課題を解決するコマンドです。特定のコミットだけを選んで別のブランチに適用できるため、ホットフィックスのバックポートや、放棄されたブランチからの変更救出に威力を発揮します。この記事では、cherry-pickの基本から実践的な使い方、そしてトラブル対処法まで詳しく解説していきます。
git cherry-pickの概要
git cherry-pickは、指定したコミットの変更内容を現在のブランチに適用し、新しいコミットとして記録するコマンドです。マージやリベースがブランチ全体を統合するのに対し、cherry-pickは個々のコミットを選択的に適用できる点が大きな特徴となっています。
内部的には3-way mergeという仕組みを使っており、対象コミットの親コミット、対象コミット、現在のHEADの3つを比較して変更を適用します。そのため、単純なパッチ適用よりも賢く差分を処理でき、多くの場合は自動的にマージが成功します。
このコマンドはGit 2.x以降で安定して動作し、関連するコマンドとしてgit revert(コミットを打ち消す)やgit merge、git rebaseがあります。これらのコマンドとの使い分けについては後ほど詳しく説明します。
cherry-pickの基本的な使い方
単一コミットの適用
最もシンプルな使い方は、コミットハッシュを指定して実行する方法です。まず適用先のブランチに切り替えてから、cherry-pickを実行します。
# mainブランチに切り替え
git checkout main
# 特定のコミットを適用
git cherry-pick abc1234コミットハッシュはgit logで確認できます。ハッシュは先頭7文字程度の省略形でも認識されます。
# コミット履歴を確認
git log --oneline feature-branch
# 出力例:
# abc1234 バグ修正: ログイン処理のエラーハンドリング
# def5678 新機能: ユーザープロフィール画面
# ghi9012 リファクタリング: 共通関数の整理便利なオプション
cherry-pick実行時にはいくつかの便利なオプションが用意されています。-xオプションを使うと、コミットメッセージに元のコミットへの参照が自動追加されます。
# オリジナルコミットへの参照を追加
git cherry-pick -x abc1234このオプションを使うと、コミットメッセージの末尾に「(cherry picked from commit abc1234…)」という行が追加され、後から追跡しやすくなります。公開ブランチ間でcherry-pickする際には特に推奨される方法です。
コミットメッセージを編集したい場合は-eオプションを使用します。
# コミットメッセージを編集して適用
git cherry-pick -e abc1234複数コミットの適用
複数のコミットを一度に適用することも可能です。スペース区切りで複数のハッシュを指定するか、範囲指定を使用します。
# 複数のコミットを個別に指定
git cherry-pick abc1234 def5678 ghi9012
# コミット範囲を指定(abc1234の次からdef5678まで)
git cherry-pick abc1234..def5678
# コミット範囲を指定(abc1234も含める)
git cherry-pick abc1234^..def5678範囲指定で注意が必要なのは、..記法では始点のコミットは含まれないという点です。始点も含めたい場合は^を付けてabc1234^..def5678のように記述します。
実践的なユースケース
ホットフィックスのバックポート
最も一般的なユースケースは、開発ブランチで修正したバグを本番ブランチに素早く適用するシナリオです。
# 開発ブランチでバグを修正してコミット
git checkout develop
# (バグ修正作業)
git commit -m "fix: ログイン時のセッション切れエラーを修正"
# コミットハッシュを確認
git log --oneline -1
# 出力: a1b2c3d fix: ログイン時のセッション切れエラーを修正
# 本番ブランチに切り替えてcherry-pick
git checkout main
git cherry-pick -x a1b2c3dこの方法なら、開発中の他の変更を含めずに、必要なバグ修正だけを本番環境にデプロイできます。
放棄されたブランチからの救出
マージされずにクローズされたPRや、長期間放置されたフィーチャーブランチから有用な変更を救い出すケースも珍しくありません。
# 削除されたブランチのコミットを探す
git reflog | grep "feature-old"
# または全コミット履歴から検索
git log --all --oneline --grep="実装したい機能名"
# 見つけたコミットを現在のブランチに適用
git cherry-pick xyz7890git reflogはローカルの参照履歴を保持しているため、ブランチが削除されていてもコミットを見つけることができます。ただし、reflogはデフォルトで90日間の履歴しか保持しない点に注意してください。
誤ったブランチへのコミットの修正
間違えて別のブランチにコミットしてしまった場合も、cherry-pickで修正できます。
# 誤ってmainにコミットしてしまった場合
git log --oneline -1
# 出力: abc1234 新機能の実装(本来はfeatureブランチ向け)
# 正しいブランチに切り替えてcherry-pick
git checkout feature-branch
git cherry-pick abc1234
# 元のブランチでコミットを取り消す
git checkout main
git reset --hard HEAD~1この手順により、コミットを正しいブランチに移動できます。ただし、既にpush済みの場合はgit revertを使う方が安全です。
コンフリクト発生時の対処法
cherry-pickでもマージと同様にコンフリクトが発生することがあります。対象コミットの変更が現在のブランチの状態と矛盾する場合に起こります。
コンフリクトの解決手順
コンフリクトが発生すると、Gitは処理を中断してユーザーに解決を求めます。
# cherry-pick実行
git cherry-pick abc1234
# 出力: CONFLICT (content): Merge conflict in src/login.js
# 出力: error: could not apply abc1234...
# コンフリクト箇所を確認
git status
# 出力: both modified: src/login.js
# ファイルを開いてコンフリクトを解決
# コンフリクトマーカー(<<<<<<<, =======, >>>>>>>)を編集
# 解決したファイルをステージング
git add src/login.js
# cherry-pickを続行
git cherry-pick --continueコンフリクト解決が難しい場合や、やり直したい場合は--abortで中断できます。
# cherry-pickを中断して元の状態に戻す
git cherry-pick --abortその他のシーケンサーコマンド
複数コミットをcherry-pick中に問題が発生した場合のためのコマンドも用意されています。
# 現在のコミットをスキップして次へ進む
git cherry-pick --skip
# 進行中の操作を忘れる(シーケンサー状態のクリア)
git cherry-pick --quit--skipは現在のコミットを諦めて次のコミットの処理に進みます。--quitは操作自体を終了しますが、既に適用済みのコミットはそのまま残ります。
よくあるエラーと解決策
空のコミットエラー
cherry-pick対象の変更が既に現在のブランチに存在する場合、空のコミットとなりエラーが発生します。
git cherry-pick abc1234
# 出力: The previous cherry-pick is now empty
# 空コミットを許可する場合
git cherry-pick --allow-empty abc1234
# 自動的にスキップする場合
git cherry-pick --empty=drop abc1234マージコミットのcherry-pick
マージコミットをそのままcherry-pickしようとすると、「mainline was not specified」というエラーが出ます。
git cherry-pick merge-commit-hash
# 出力: error: commit xxx is a merge but no -m option was given
# 親番号を指定して実行(通常は-m 1)
git cherry-pick -m 1 merge-commit-hash-m 1は最初の親(マージ先のブランチ)を基準とした差分を適用します。マージ元の変更を適用したい場合は-m 2を指定します。
cherry-pickの取り消し
間違ってcherry-pickしてしまった場合の取り消し方法は、push済みかどうかで異なります。
# まだpushしていない場合(直前のコミットを削除)
git reset --hard HEAD~1
# 既にpushした場合(revertで打ち消しコミットを作成)
git revert <cherry-picked-commit-hash>push済みのコミットをresetで消すと、他の開発者の環境と不整合が起きるためrevertを使用します。
merge・rebaseとの使い分け
cherry-pickは便利なコマンドですが、常に最適な選択肢というわけではありません。以下の表を参考に、状況に応じて使い分けましょう。
| 操作 | 用途 | 結果 | 推奨シーン |
|---|---|---|---|
| merge | ブランチ全体の統合 | マージコミットあり、非線形履歴 | フィーチャーブランチの統合 |
| rebase | ブランチの更新、履歴整理 | 線形履歴、コミット書き換え | ローカル作業の整理 |
| cherry-pick | 特定コミットの選択的適用 | 新規コミット生成 | ホットフィックス、救出 |
cherry-pickの注意点として、同じ変更内容でも新しいSHAハッシュを持つコミットが生成されるという点があります。これにより、後でブランチをマージした際にコンフリクトが発生する可能性があります。
そのため、ブランチ全体を統合する予定がある場合はmergeを、履歴を整理しながら更新したい場合はrebaseを選択するのが基本です。cherry-pickはホットフィックスや救出操作など、本当に個別のコミットだけが必要な場面に限定して使用することをお勧めします。
ベストプラクティス
実務でcherry-pickを使う際に意識したいポイントをまとめます。
まず、公開ブランチ間でcherry-pickする際は-xオプションを使用して、オリジナルコミットへの参照を残しましょう。これにより、どのコミットから派生したかを後から追跡できます。ただし、プライベートな作業ブランチからのcherry-pickでは不要です。
次に、cherry-pickを効果的に使うには、日頃から小さく焦点を絞ったコミットを心がけることが重要です。複数の変更が混在した大きなコミットは、一部だけを取り出すことが難しくなります。「1コミット1目的」を意識すると、cherry-pickに限らずGit操作全般がスムーズになります。
また、チーム開発でcherry-pickを行った場合は、必ずチームメンバーに共有しましょう。同じ変更が異なるSHAで複数存在することを認識してもらうことで、将来のマージコンフリクトを防止できます。SlackやPRのコメントで「○○のコミットをmainにcherry-pickしました」と一言伝えるだけで十分です。
よくある質問
cherry-pickとrebaseの違いは何ですか?
rebaseは現在のブランチのコミットを別のブランチの先端に移動させる操作で、ブランチ全体に影響します。一方、cherry-pickは指定したコミットを現在のブランチにコピーする操作で、元のコミットはそのまま残ります。また、rebaseは現在ブランチのコミットを移動するのに対し、cherry-pickは他のブランチのコミットを現在のブランチにコピーするという方向の違いもあります。
cherry-pickしたコミットを取り消すには?
まだpushしていない場合はgit reset --hard HEAD~1で直前のコミットを削除できます。既にpush済みの場合はgit revert <commit-hash>で打ち消しコミットを作成するのが安全です。
複数のcherry-pickを1つのコミットにまとめられますか?
-n(–no-commit)オプションを使用すると、変更をワーキングツリーに適用するだけでコミットは作成されません。複数のcherry-pickを-n付きで実行した後、まとめて1回コミットすることで実現できます。
まとめ
git cherry-pickは、特定のコミットだけを別のブランチに適用できる便利なコマンドです。ホットフィックスのバックポート、放棄されたブランチからの変更救出、誤ったブランチへのコミット修正など、様々な場面で活躍します。
ただし、cherry-pickは重複コミットを生成するため、可能な限りmergeやrebaseを優先し、本当に必要な場面に限定して使用することをお勧めします。-xオプションでオリジナルコミットへの参照を残す、チームに共有するなどのベストプラクティスを意識することで、より安全にcherry-pickを活用できます。
まずは安全なテスト環境で基本的な操作を試してみてください。コンフリクト解決の練習も含めて経験を積むことで、いざという時に自信を持って使えるようになります。
参考リンク
Git Cherry Pick | Atlassian Git Tutorial
How git cherry-pick and revert use 3-way merge | Julia Evans



