web-dev-qa-db-ja.com

git cherry-pickは、「... 38c74dはマージですが、-mオプションが指定されていません」と表示します。

私は私のマスターブランチにいくつかの変更を加え、それらを上流に持って行きたいです。私が以下のコミットをチェリーピックしたとき、しかし私はgitが言うところのfd9f578で立ち往生します:

$ git cherry-pick fd9f578
fatal: Commit fd9f57850f6b94b7906e5bbe51a0d75bf638c74d is a merge but no -m option was given.

Gitは私に何を伝えようとしていますか。ここで使用するのに適したものを選んでいますか? masterブランチには上流ブランチで変更されたファイルへの変更が含まれています、それで私はいくらかのマージコンフリクトがあるだろうと確信しています、しかしそれらはまっすぐにするためにそれほど悪くないです。どこでどの変更が必要かを知っています。

これらは私が上流に持ってきたいコミットです。

e7d4cff added some comments...
23e6d2a moved static strings...
44cc65a incorporated test ...
40b83d5 whoops delete whitspace...
24f8a50 implemented global.c...
43651c3 cleaned up ...
068b2fe cleaned up version.c ...
fd9f578 Merge branch 'master' of ssh://extgit/git/sessions_common
4172caa cleaned up comments in sessions.c ...
406
wufoo

チェリーピックが機能する方法は、チェンジセットが表す差分(その時点の作業ツリーとその親の作業ツリーの違い)を取り、それを現在のブランチに適用することです。

それで、コミットが2つ以上の親を持つ場合、それは2つ以上の差分も表します - どちらが適用されるべきですか?

あなたはfd9f578を選択しようとしています、それは2人の親との合併でした。そのため、-mオプションを使用して、差分を計算する対象となるものに対してcherry-pickコマンドに指示する必要があります。たとえば、親1をベースとして使用する場合はgit cherry-pick -m 1 fd9f578です。

私はあなたの特定の状況について確実に言うことはできませんが、git mergeの代わりにgit cherry-pickを使うことは一般的にお勧めです。マージコミットを選択すると、 all -mに指定していない親で行われた変更がその one commit に折りたたまれます。あなたは彼らのすべての歴史を失い、そしてすべての彼らのdiffを一緒に輝かせます。あなたの電話.

486
Borealid

@Borealidの答えは正しいですが、ブランチの正確なマージ履歴を保存することを気にせず、その線形化バージョンをチェリーピックしたいだけだとします。これを行う簡単で安全な方法を次に示します。

開始状態:ブランチX上にあり、コミットY..Zをチェリーピックしたい場合。

  1. git checkout -b tempZ Z
  2. git rebase Y
  3. git checkout -b newX X
  4. git cherry-pick Y..tempZ
  5. (オプション)git branch -D tempZ

これは、tempZに基づくブランチZを作成しますが、Y以降の履歴を線形化し、XというnewXのコピーにそれをチェリーピックします。 (Xを変更するよりも、新しいブランチでこれを行う方が安全です。)もちろん、通常の方法で解決する必要があるステップ4で競合が発生する場合があります(cherry-pickは、rebaseその点)。最後に、一時的なtempZブランチを削除します。

手順2で「現在のブランチtempZは最新です」というメッセージが表示された場合、Y..Zはすでに線形であったため、そのメッセージを無視して手順3以降に進みます。

次に、newXを確認し、それが目的どおりに実行されたかどうかを確認します。

(注:これは、ZXの関係にまったく依存しないため、ブランチYにあるときの単純なgit rebase Xとは異なります。共通の祖先とYの間には、望まなかった。)

25
Daira Hopwood

-mは親番号を意味します。

Gitのドキュメントから:

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

たとえば、コミットツリーが以下のようになっているとします。

- A - D - E - F -   master
   \     /
    B - C           branch one

git cherry-pick Eはあなたが直面している問題を引き起こします。

git cherry-pick E -m 1D-Eを使用することを意味し、git cherry-pick E -m 2B-C-Eを使用することを意味します。

6
gavincook

考えられるアプローチの利点/リスクを理想的に明確にする、受け入れられた答えを書き直したものです。

あなたは2人の親との合併であったfd9f578をチェリーピックしようとしています。

マージを選択するのではなく、最も簡単な方法は、マージの各ブランチから実際に必要なコミットを選択することです。

あなたは既にマージしているので、それはあなたが望む全てのコミットがあなたのリストにある可能性が高いです。それらを直接選択してください。マージコミットをいじる必要はありません。

説明

チェリーピックが機能する方法は、チェンジセットが表す差分(その時点のワーキングツリーとその親のワーキングツリーの違い)を取得し、そのチェンジセットを現在のブランチに適用することです。

マージの場合のように、コミットに2つ以上の親がある場合、そのコミットも2つ以上の差分を表します。どのdiffを適用すべきかについての不確実性のためにエラーが発生します。

代替案

マージと関連コミットのチェリーピッキングを含める必要があると判断した場合は、2つの選択肢があります。

  1. (より複雑であいまいになります。履歴も破棄します)どちらの親を当てはめるかを指定できます。

    • そのためには-mオプションを使用してください。たとえば、git cherry-pick -m 1 fd9f578は、マージにリストされている最初の親をベースとして使用します。

    • また、マージコミットを選択すると、all-mに指定していない親で行われた変更がその1コミット。すべての履歴を失い、一緒に輝く)になることも考慮してください。あなたの電話。

  2. (よりシンプルでより身近なもの、歴史を保存する)git mergeの代わりにgit cherry-pickを使うことができます。

    • git mergeと同じように、マージしているブランチに存在するすべてのコミットを適用し、それらをgitログに個別にリストしようとします。
5
Kay V

単一のコミットを選択するのに適した@Daira Hopwoodメソッドの単純化一時的な分岐は必要ありません。

作者の場合:

  • Zがコミットされている(fd9f578)
  • Yはその前にコミットする
  • Xカレントワーキングブランチ

それから:

git checkout Z   # move HEAD to wanted commit
git reset Y      # have Z as changes in working tree
git stash        # save Z in stash
git checkout X   # return to working branch
git stash pop    # apply Z to current branch
git commit -a    # do commit
1
ephemerr