コミットをあるブランチから別のブランチにコピーする方法は?


728

私はマスターから2つのブランチを持っています:

  • v2.1:(バージョン2)数か月間取り組んできました
  • wss:特定の機能をマスターに追加するために昨日作成した(運用中)

昨日のコミットをwssからv2.1にコピーする方法はありますか?


:単純にこの答えは最高の私を助けた別のブランチからコミット(またはコミットの範囲)をコピーするにはstackoverflow.com/questions/1994463/...
caramba

回答:


566

あなたは本当にこれをマージすることでこれをすべて可能にするワークフローを持っているはずです:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

されるすべてあなたがしなければならないので、git checkout v2.1git merge wss。なんらかの理由で本当にこれを行うことができず、git rebaseを使用してwssブランチを適切な場所に移動できない場合、単一のコミットをどこかから取得して別の場所に適用するコマンドはgit cherry-pickです。適用したいブランチをチェックアウトして、を実行してくださいgit cherry-pick <SHA of commit to cherry-pick>

リベースによって節約できるいくつかの方法:

履歴が次のようになっている場合:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

git rebase --onto v2 v2-only wsswssをv2に直接移動するために使用できます。

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

その後、マージできます!本当に、本当に、本当にマージできるポイントに到達できない場合でも、リベースを使用して、一度に複数のチェリーピックを効果的に実行できます。

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

注:これを行うために追加の作業が必要になる理由は、リポジトリに重複したコミットを作成するためです。これは本当に良いことではありません。簡単な分岐とマージのポイントは、コミットを1か所にして、必要な場所にマージすることですべてを実行できるようにすることです。コミットの重複は、これらの2つのブランチを決してマージしないことを意味します(後で行う場合は、競合が発生します)。


1
この回答にこれ以上同意できませんでした。+1。:チェリーピッキングの結果を示すにも私の古い答えを参照してくださいstackoverflow.com/questions/881092/...を
VonC

18
これを適切に行う方法についてのすばらしい答え!また、ASCIIダイアグラムを作成するためにも、2回賛成票を投じることができればと思います。
gotgenes 2010年

@VonC:サポートに感謝し、なぜチェリーピックしないのかについての追加情報-私はそこを少し見逃していることを知っています。@gotgenes:ありがとう!努力する価値は十分にあると思います-git-rebaseのマンページをご覧ください。それを説明するより良い方法はありません。
Cascabel

なぜマージできないのか-Gitマージはgit-svnではうまく機能しません。一連のコミットを1つのSVNブランチから別のブランチにコピーするために、私はそれらをチェリーピックし、インタラクティブなリベース/リワードを実行して、正しくないgit-svn-id参照を削除してから、dcommit再度実行しました。私はおそらくチェリーピックのステップを省略して、リベースを単独で使用しただけかもしれません。
ボブ

1
これが私のユースケースです:重要なバグ修正が機能ブランチにコミットされました。私は今、生産に入るのにマスターでそれを必要とします。これは私のお尻を保存します。
キャプテンハイパーテキスト2016

910

使用する

git cherry-pick <commit>

現在のブランチに適用<commit>する。

私自身はおそらく私が選んだコミットをクロスチェックし、gitk代わりにそこのコミットエントリを右クリックしてそれらをチェリーピックします。


もっと自動化したい場合(そのすべての危険性あり)、昨日のwssでのコミット以降のすべてのコミットを想定して、git log--prettyJefromiによって提案された)を使用してコミットのリストを生成できます。

git log --reverse --since=yesterday --pretty=%H

だからあなたが使うことを想定してすべて一緒に bash

for commit in $(git log --reverse --since=yesterday --pretty=%H);
do
    git cherry-pick $commit
done

ここで問題が発生した場合(潜在的な可能性がたくさんあります)、これはライブチェックアウトで機能するので問題があります。


--prettyオプションのすべてのプレースホルダーは、git-logのマンページにあります。必要な任意の形式を取得できます。特に、スクリプトに必要なフィールドを簡単に解析可能な形式で取得するのに役立ちます。
Cascabel

また、あなたが本当に重複したコミットを作成したいのであればgit rebase、私の答えで使用する方法はより堅牢であることも指摘しておきます。特に、このようなforループを使用すると、チェリーピックの1つが失敗した場合でも、残りのすべてを実行しようとします。これは...非常に良くない、としましょう。
Cascabel

2
同意した。それが私がそれを使用したことがない理由ですが、手動で行います。しかし、少なくとも質問のタイトルに対するチェリーピックは依然として答えです。応答を変更しました。
Benjamin Bannier

1
誰かが古い/正しくないブランチにコミットし、チェリーピックにより、そのコミットを正しいブランチに入れることができました(まだコミッターとして維持しています)。完璧です。
Patrick 14

8
珍しい光景、git解答に対して単純で正解な答えであり、回答者がそれをどれだけよく知っているかを証明するためにgitの複雑さを蛇行するのではなく。
Przemek D 2017

74

git cherry-pick :既存のコミットによって導入された変更を適用します

(X、Y、Z)コミットのブランチAがあるとします。これらのコミットをブランチBに追加する必要があります。cherry-pickオペレーションを使用します。

を使用する場合、ブランチAにコミットが表示されるのと同じ時系列cherry-pickでブランチBにコミットを追加する必要があります。

cherry-pickは一連のコミットをサポートしていますが、その範囲にマージコミットがある場合、それは本当に複雑になります

git checkout B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

ワークフローの例:

ここに画像の説明を入力してください

私たちは、使用することができますcherry-pickオプション

-eまたは--edit:このオプションを使用すると、git cherry-pickを使用すると、コミットする前にコミットメッセージを編集できます。

-nまたは--no-commit:通常、コマンドは一連のコミットを自動的に作成します。このフラグは、コミットを行わずに、名前付きの各コミットを作業ツリーとインデックスにチェリーピックするために必要な変更を適用します。さらに、このオプションを使用する場合、インデックスはHEADコミットと一致する必要はありません。チェリーピックは、インデックスの初期状態に対して行われます。

ここに興味深い記事がありcherry-pickます。


19

あなたは可能性がパッチを作成し、あなたがコピーしたいコミットからパッチを適用する先のブランチに。


16
何らかの理由で、cherry-pick(s)/ rebaseの代わりにパッチを本当に使用したい場合でも、それを行う簡単な方法は、git format-patch <revision range>およびを使用することですgit am *.patch
Cascabel

checkout別のブランチに必要です。
CoolMind

12

または、伝道者の側が少し少ない場合、私が使用している少し醜い方法を実行できます。deploy_templateには、ブランチデプロイとしてマスターにコピーするコミットがあります

git branch deploy deploy_template
git checkout deploy
git rebase master

これにより、deploy_templateに新しいブランチデプロイ(-fを使用して既存のデプロイブランチを上書きします)が作成され、この新しいブランチがマスターにリベースされ、deploy_templateは変更されません。


1

ブランチのwssからv2.1に最後のコミットをコピーするだけの単純なケースでは、コミットID(git log --oneline | head -n 1)を取得して次のように実行できます。

git checkout v2.1
git merge <commit>

これには、別のブランチにチェックアウトする必要があります。
CoolMind

1

cherry-pickコマンドは、標準入力からコミットのリストを読み取ることができます。

次のコマンドcherry-picksは、ユーザーJohnによって作成され、「開発」ブランチには存在するが「リリース」ブランチには存在しないコミットを時系列順にコミットします。

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.