web-dev-qa-db-ja.com

Git Cherry-Pick構文とマージブランチ

だから私は以前に数え切れないほどのチェリーピックを行ってきましたが、今はこれで人生で失敗しなければならないようです、私はあるブランチから別のブランチにチェリーピックをしようとしています-mが指定されていませんか?

$ git cherry-pick a8c5ad438f6173dc34f6ec45bddcef2ab23285e0
error: Commit a8c5ad438f6173dc34f6ec45bddcef2ab23285e0 is a merge but no -m option was given.
fatal: cherry-pick failed

それは間違っているように見えます。

$ git cherry-pick a8c5ad438f6173dc34f6ec45bddcef2ab23285e0

いつから-m関数を指定する必要があるのですか?

57
TheWebs

コミットがマージマージの場合、つまり複数の親を持つコミットの場合は、-mを指定する必要があります。

通常、git cherry-pick REVは次のように記述できます。

  1. revとその親の間の変更を取得します。

  2. これらの変更を現在のHEADに適用し、revのコミットメッセージで結果をコミットします。

マージコミットは、2つの開発ラインを結合します。たとえば、一方の行はウィジェットを実装し、もう一方の行は混乱を取り除きます。マージにより、ウィジェットを備えたコードが得られます。

さて、チェリーピックプロセスのステップ1について考えてみましょう。gitは、クラッターを削除するのか、ウィジェットを実装するのかを推測できません。また、両方を行う方法に関する情報は単一のマージコミットに含まれておらず、結果のマージされたツリーのコンテンツのみが含まれているため、両方を行うことはできません。

-mオプションを使用すると、gitに処理方法を指示できます。たとえば、masterでクラッターの削除が行われ、git merge WIDGETを使用してマージコミットが作成された場合、git cherry-pick -m 1 merged-commitは、マージされたツリーと親1の差分クラッターを除去する最後のコミット)は、まさにウィジェットの追加です。一方、git cherry-pick -m 2 merge-commitはクラッターを削除します。これは、親2(ウィジェットを追加する最後のコミット)とmerge-commitの違いが、クラッター除去が欠落しているためです。 ウィジェットブランチ。

74
user4815162342

Gitは親番号(-m)の指定を要求しています。これは、マージコミットに2つの親があり、gitがどちらの側かわからないためです。マージをメインラインと見なす必要があります。したがって、このオプションを使用すると、メインラインとチェリーピックの親番号(1から始まる)を指定して、指定された親に関連する変更を再生できます。

コミットの親を見つけるには、次のいずれかを試してください。

git show --pretty=raw <merge_commit>

または:

git cat-file -p <merge_commit>

または、GUIの可視性を向上させるために、以下を試してください。

gitk <merge_commit>

その結果、次のようになります。

commit fc70b1e9f940a6b511cbf86fe20293b181fb7821
tree 8d2ed6b21f074725db4f90e6aca1ebda6bc5d050 
parent 54d59bedb9228fbbb9d645b977173009647a08a9 = <parent1_commit>
parent 80f1016b327cd8482a3855ade89a41ffab64a792 = <parent2_commit>

次に、次の方法で各親の詳細を確認します。

git show <parent1_or_2_commit>

--statを追加して、変更されたファイルのリストを表示します。

または、次のコマンドを使用して、変更を比較します(上記の親に基づいて)。

git diff <parent1_or_2_commit>..<commit>

--statを追加して、変更されたファイルのリストを表示します。

または、組み合わせたdiffを使用して、次の方法で2つの親を比較します。

git diff --cc <parent1_commit>
git diff --cc <parent2_commit>

次に、チェリーピックの1から始まる親番号を指定します。

git cherry-pick -m 1 <merge_commit>

次に、git statusを実行して、何が起こっているのかを確認します。まだ変更をコミットしたくない場合は、-nオプションを追加して、何が起こるかを確認してください。その後、満足できない場合はHEAD(git reset HEAD --hard)にリセットします。gitの競合が発生する場合は、おそらく手動で解決するか、マージ戦略を指定する必要があります( -X)、参照: Gitでマージの競合を解決する方法?

17
kenorb

個人的に私が通常していることは、マージが2つのコミットを組み合わせているためです。たとえば、2つの親で構成されるマージコミットCがある場合、たとえばマスターのコミットAとマージされている他のブランチのコミットB、チェリーピックする必要がある場合マージマージコミット自体をチェリーピックする混乱するコマンドに煩わされることはありませんが、代わりに親AとBのそれぞれを個別にチェリーするだけで、コミットBのみをチェリーピックする場合に役立ちますマスターからのケースコミットAは、マージが発生する前にすでにチェリーピッキングされているブランチにピッキングされました。

3
Wyclif

マニュアルページの構文は次のとおりです。

git cherry-pick [--edit] [-n] [-m parent-number] [-s] [-x] [--ff] <commit>...

親番号は以下を参照します:

-m parent-number、--mainline parent-number、通常、マージのどちら側をメインラインと見なすべきかわからないため、マージをチェリーピックできません。このオプションは、メインラインの親番号(1から始まる)を指定し、チェリーピックが指定された親に関連する変更を再生できるようにします。

だから、私はあなたが正しいコミットハッシュを持っていることを確認するためにダブルチェックするでしょう。マージからのものではなく、その前のコミットからのものが必要な場合があります。それ以外の場合は、このフラグを使用して、マージの正しい側をポイントして、要求を明確にする必要があります。

2
Magikhead