git cherry-pick: 1つのコミットを別のブランチに移す方法
git cherry-pick は、指定したコミットの変更を取り出し、現在のブランチに同じ差分とメッセージを持つ新しいコミットを作ります。ハッシュは別になります。移動先のブランチに切り替えてから git cherry-pick ハッシュ を実行します。コンフリクトが起きたら、ファイルを修正して git add と git cherry-pick --continue を実行します。
git cherry-pick は、特定のコミットの変更だけを現在のブランチに移します。ブランチ全体を統合するわけではありません。Gitは選んだコミットの親との差分を計算し、それを現在の HEAD に適用して新しいコミットを作ります。メッセージと作成者は同じですが、親が異なるためハッシュは変わります。
典型的な場面は次のとおりです。機能のブランチでバグを直したが、その修正がまだ完成していない機能を含むリリースブランチにも急ぎで必要になった。ブランチ全体は統合できませんが、1つのコミットなら移せます。
1つのコミットを別のブランチに移す
まず目的のコミットのハッシュを見つけ、移したい先のブランチに切り替えて cherry-pick を実行します。
# 1. feature ブランチでコミットを探す
git log --oneline feature
a1b2c3d 割引計算でゼロ除算を修正
9f8e7d6 支払い画面を追加
# 2. 移動先のブランチに切り替える
git switch release-1.4
# 3. コミットを移す
git cherry-pick a1b2c3d
[release-1.4 4e5f6a7] 割引計算でゼロ除算を修正
Date: Mon Oct 5 14:12:03 2026 +0300
1 file changed, 3 insertions(+), 1 deletion(-)
新しいコミットのハッシュは 4e5f6a7 で、a1b2c3d ではありません。これは変更内容が同じ、別々のオブジェクトです。元のブランチ feature は変わりません。
ハッシュの代わりに、コミットを指す任意の参照を使えます。git cherry-pick feature は feature の最後のコミットを、git cherry-pick feature~2 は末尾から3番目のコミットを移します。
複数のコミットを移す
一覧で指定する
ハッシュを一覧で渡すこともできます。Gitは指定した順番に適用し、同じ数の新しいコミットを作ります。
git cherry-pick a1b2c3d 7c8d9e0 3f4a5b6
順番は重要です。2つ目のコミットが1つ目に依存している場合、逆の順番で指定するとコンフリクトになるか、コードが壊れます。古いものから新しいものの順で指定するのが安全です。
範囲で指定する
連続するコミットには範囲の書き方を使います。ここには、ほぼ全員がつまずく罠があります。A..B は「B からたどれて A からはたどれないコミット」を意味し、A 自身は範囲に含まれません。
# A の後から B まで(B を含む)を移す
git cherry-pick A..B
# A から B まで(A と B を含む)を移す
git cherry-pick A^..B
feature にあって main にないものをすべて移したい場合は git cherry-pick main..feature が便利です。ただし、コミットが多い場合は、cherry-pick ではなく rebase や merge が必要ではないかを検討してください。
git cherry-pick の便利なオプション
| オプション | 動作 | 使いどころ |
|---|---|---|
-x | メッセージに「(cherry picked from commit …)」の行を追加する | 公開されたブランチ間で修正を移すとき。移し元が分かる |
-n、--no-commit | コミットせずに、変更をインデックスと作業ディレクトリに適用する | 複数のコミットを1つにまとめたいとき、またはコミット前に手直ししたいとき |
-e、--edit | メッセージを編集するためにエディタを開く | 移し先のブランチに合わせてメッセージを直したいとき |
-s、--signoff | Signed-off-by の行を追加する | DCO を要求するプロジェクト |
-m 1 | マージコミットの「主」の親を指定する | マージコミットを移すとき |
--ff | HEAD が選んだコミットの親である場合、ブランチを先に進めるだけにする | まれに使う。重複を作らずに済む |
--allow-empty | 元々空のコミットの移動を許可する | 意図的な空のコミット |
-x を使う理由
半年後に誰かがリリースブランチで修正を見つけ、その出所を知りたくなるかもしれません。-x で追加された行が、その答えを直接示します。
git cherry-pick -x a1b2c3d
git log -1
割引計算でゼロ除算を修正
(cherry picked from commit a1b2c3d4e5f60718293a4b5c6d7e8f9012345678)
-x は、元のコミットがすでに公開されている場合に使います。後で削除するローカルブランチから移す場合、リンク先が存在しなくなるので、このフラグは不要です。
-n で複数のコミットを1つにまとめる
git cherry-pick -n a1b2c3d 7c8d9e0
git status # 両方のコミットの変更がインデックスにある
git commit -m "割引計算の修正をまとめて反映"
cherry-pick のコンフリクトと解決方法
コミットの変更が現在のコードに合わないときにコンフリクトが起きます。移し先のブランチでは、同じ行がすでに違う形になっているのです。Gitは停止して報告します。
git cherry-pick a1b2c3d
Auto-merging src/discount.js
CONFLICT (content): Merge conflict in src/discount.js
error: could not apply a1b2c3d... 割引計算でゼロ除算を修正
hint: After resolving the conflicts, mark them with
hint: "git add/rm <pathspec>", then run
hint: "git cherry-pick --continue".
ここからは3つの選択肢があります。
- 解決して続ける。 ファイルを開き、
<<<<<<<、=======、>>>>>>>のマーカーを取り除き、正しい版を残します。その後git add src/discount.jsとgit cherry-pick --continueを実行します。 - コミットを飛ばす。 複数のコミットを移している場合、
git cherry-pick --skipで問題のコミットを飛ばし、次に進みます。 - すべてやめる。
git cherry-pick --abortで、操作を始める前のブランチの状態に戻します。
また git cherry-pick --quit もあります。これは操作を止めますが、すでに適用されたコミットと現在のファイルの状態は残します。リストの半分を移し終えて、残りを手作業で行いたい場合に便利です。
同じコンフリクトが何度も発生する場合(たとえば、複数のリリースブランチに修正を定期的に移す場合)は、git config rerere.enabled true を設定してください。Gitは解決方法を記憶し、次回から自動で適用します。
マージコミットを移す
マージコミットには親が2つあり、Gitはどちらとの差分を取るべきか分かりません。ヒントがないと、次のようなエラーになります。
git cherry-pick 5d6e7f8
error: commit 5d6e7f8 is a merge but no -m option was given.
-m 1 は「最初の親(通常は統合先のブランチ)との差分を使う」という意味です。これで、統合されたブランチが持ち込んだ変更を、1つのコミットとして移せます。
git cherry-pick -m 1 5d6e7f8
ただし、この後もGitはブランチを統合済みとは見なしません。今後マージを行うと、同じ変更をもう一度適用しようとすることがあります。
git cherry-pick と git apply の違い
git apply は cherry-pick と並べて語られることがよくあります。どちらも「変更を重ねて適用する」ものですが、入力が異なります。
| git cherry-pick | git apply | |
|---|---|---|
| 入力 | リポジトリにあるコミット | パッチファイル(差分) |
| コミットを作るか | 作る(-n を付けない場合) | 作らない。ファイルを変更するだけ(--index を付けるとインデックスも変わる) |
| 作成者とメッセージの保持 | 保持する | 保持しない。パッチにはそれらがない |
| コンフリクト | マーカー付きの3方向マージ | 既定では失敗するだけ。--3way ならマーカーを付ける |
| 共通のリポジトリが必要か | 必要。コミットがローカルで使える必要がある | 不要。パッチは任意の方法で渡せる |
コミットが自分のリポジトリにない場合の git apply の例です。同僚がファイルで差分を送ってきた場合などです。
# 同僚の作業
git diff main..fix-discount > fix.patch
# あなたが確認して適用する
git apply --check fix.patch # パッチが適用できるかを確認
git apply fix.patch # 作業ディレクトリに適用
git apply --3way fix.patch # 食い違いがあればコンフリクトマーカーを付ける
作成者とメッセージを含めてコミット全体を渡したい場合は、git format-patch と git am の組み合わせを使います。前者はコミットをファイルに保存し、後者はそれらからコミットを作ります。言わば「メールで送る cherry-pick」です。
別のリポジトリからの cherry-pick も可能です。そのリポジトリを remote として追加し、git fetch を実行すれば、コミットがハッシュで使えるようになります。
cherry-pick が向かない場面
cherry-pick は重複を作ります。同じ変更が2つのハッシュで履歴に存在することになります。少量なら問題ありませんが、次のような場面では害になります。
- 数十個のコミットを移す。 ブランチのほぼ全体を移すなら、rebase か merge を使うべきです。cherry-pick では、重複の長い履歴と、より多くのコンフリクトが生まれます。
- 双方向の移動。 コミットを feature から main に移し、その後 feature を main に統合する場合です。通常 Git は対処できます(変更が一致するため)。しかし、移した後に同じ行が変更されていると、思わぬコンフリクトが起きます。
- 依存関係のあるコミット。 あるコミットが、2つ前のコミットで追加された関数を使っている場合、そのコミットだけを移すと移し先のコードはビルドできません。移した後は必ずビルドとテストを確認してください。
ホットフィックスの良い習慣は、最も古い保守中のブランチで修正を行い、そこから新しいブランチへ統合していくことです。そうすれば、cherry-pick は例外的な場合にだけ必要になります。
cherry-pick を取り消す
操作がまだ進行中(コンフリクトの途中)なら git cherry-pick --abort を実行します。コミットがすでに作られていて、サーバーに送っていない場合は、次のように取り除きます。
git reset --hard HEAD~1
コミットが共有ブランチにすでに push されている場合は、履歴を書き換えてはいけません。逆向きのコミットを作ります。
git revert 4e5f6a7
reset を行ったあとで考えを変えた場合でも、失ったコミットは git reflog から見つけられます。
コミットがすでに移されているか確認する
ハッシュが異なるため、通常の git branch --contains では判断できません。Gitは変更内容(patch-id)でコミットを比較できます。
git cherry -v release-1.4 feature
- a1b2c3d 割引計算でゼロ除算を修正
+ 9f8e7d6 支払い画面を追加
マイナスは、同じ変更が release-1.4 にすでにあることを、プラスは、まだないことを意味します。別の方法として、同じ内容のコミットを隠す git log --cherry-pick --oneline release-1.4...feature もあります。-x を使っていれば、メッセージで検索できます: git log --grep="cherry picked from commit a1b2c3d"。
まとめ
git cherry-pick は、ピンポイントで使う道具です。ホットフィックスをリリースに移す、放置されたブランチから役立つコミットを取り出す、誤った場所に作ったコミットを移し直す、といった用途に向いています。覚えておくべきは3つです。新しいコミットには新しいハッシュが付くこと、範囲 A..B には A が含まれないこと、公開されたブランチでは -x を付けること。コミットではなく差分をファイルとして扱うなら git apply を使います。rebase、stash、cherry-pick、タグの詳しい使い方は、Gitコースで実践的に扱っています。
よくある質問
cherry-pick は元のブランチを変更しますか?
いいえ。元のコミットはそのまま残り、現在のブランチに新しいハッシュを持つコピーが作られます。
リモートブランチのコミットを cherry-pick できますか?
はい。git fetch を実行すると、そのコミットはハッシュで使えるようになり、また origin/ブランチ名 としても参照できます。そのまま git cherry-pick に渡せます。
cherry-pick の後、なぜハッシュが変わるのですか?
ハッシュは親のコミット、コミット日時、ツリーの内容から計算されます。コピーは親が異なり、コミッターの日時も異なるため、ハッシュも別になります。
cherry-pick では作成者は保持されますか?
はい。作成者と作成日時は元のコミットから引き継がれ、コミッターとして自分と現在の日時が記録されます。
cherry-pick したら「空のコミット」と表示されました。どうすればよいですか?
その変更がすでにブランチにあるということです。git cherry-pick --skip で飛ばすか、git commit --allow-empty で空のコミットとして記録できます。