21

Git のマージに関して、説明も分類もできない奇妙な問題が発生しています。コミットの欠落ですか。マージが間違っていますか?壊れたデータですか?リポジトリの履歴は次のようになります。

master----\----commit A----cherry-picked changesets from topic---commit B--\----commit C----merge---
           \                                                                \              /
            topic-----------------------------------------------------------merge---------/

さて、私の問題はmaster、ブランチにマージされたときtopic(コミットAとBで最新のものにするため)、コミットBによって導入された変更セットがそこにないということです! コミット B がファイルfoo&を変更barしていた場合、ロットを取得しても、それらのファイルがマージで変更されたことは表示されません。ファイルに競合さえなくfoobar

にマージしtopic て戻すとmaster、コミット B は実質的に反転され、ログや反転の痕跡はありません!

何がうまくいかなかったのでしょうか?

4

2 に答える 2

12
master----\----commit A----cherry-picked changesets from topic---commit B--\----commit C----merge---
           \                                                                \              /
            topic-----------------------------------------------------------merge---------/
                                                                            ~~~~~
                                                                              ^
                                                                              + here you merged B in topic

親としてコミット B を持つトピックに既にマージがあります。したがって、B はトピックに完全にマージされ、もうどこにもマージされません。

トピックに変更がないため、マージ自体または次のコミットのいずれかで、トピックにそれらを元に戻したようです。このような反転は、マージ アルゴリズムの通常のコミットであり、マスターにはマージされません。したがって、トピックをマスターにマージすると、このコミットの変更がマージされ、コミット B が元に戻ります。

B からの変更を元に戻すには、次のいずれかを行う必要があります。

  • トピックに関する B の変更の反転を見つけて元に戻します。
  • git cherry-pick BB ( ) を話題にチェリーピック。
  • マージをやり直し、マージ後に新しいマージでトピックをリベースし、元のブランチを忘れてください。

あなたが気付かないうちに、変更がどのように元に戻された可能性がありますか? マージ中に競合が発生した場合、これらの変更はまだ必要ないと考えて、「ローカル」を使用してずさんに解決する可能性があります。しかし、Git (またはその他のバージョン管理システム) の観点から見ると、変更を確認して拒否したため、二度と取得することはありません。手動で再適用しない限り。

競合は、以前のチェリーピックによって簡単に引き起こされた可能性があります. 両方の側が同じに見える場合、アルゴリズムは競合を宣言しませんが、チェリーピックしてマージする場合、チェリーピックされたコードを一方の側で変更すると競合を宣言します。あなたが持っているとしましょう:

----\-- A -------- B' -- B2 --\
     \                         \
      D -- B -- E -----------merge

whereは、行ったのと同じコードを選択して変更B'Bます。その場合、チェリーピックは によって隠されているため、との間の競合を宣言するため、マージは一方の側がを行い、もう一方の側が を行ったことを確認します。そして、歴史を注意深く見なければ、この間違いを簡単に解決してしまうかもしれません。コミットを選択するときに、次のようにターゲットブランチをソースブランチに慎重にマージすると、問題を回避できます。B2BBB2B2BB2

----\-- A --------\- B' -\- B2 --\
     \             \      \       \
      D -- B -- E --m1-----m2----merge

リモートではチェリーピックされた変更のみが含まれているため、m1チェリーピックが関与しない通常のマージでありm2、ローカルバージョンで解決されます。これにより、以降のマージが正しく機能することが保証されます。

実際には、git がこれを自動的に行うためのマージ戦略を作成できるはずです。

于 2012-11-20T08:04:55.427 に答える
2

なぜそこにないのかはわかりませんが、にマージするのではなく、上にBリベースすることをお勧めします。topicmastermastertopic

チェリーピックされたコミットはに複製されますが、同じコミットがすでに存在するブランチ( )masterにマージする場合はうまく機能しません。これは、次の上に リベースする場合とは異なります。重複するコミット再生されません。mastertopic
topicmaster

もちろん、リベースの問題は、SHA1の変更です。これは、すでにアップストリームリポジトリにtopicプッシュしている場合(および他の人がすでにプルしている場合)に問題になります。topictopic

一般に、「共有機能ブランチを使用した適切なgitワークフローは何ですか? 」に示されているように、「バックマージ」(masterto topic)を避け、主に1つの方法(topicto master)でのみマージを使用する必要があります。

于 2012-11-20T07:06:03.530 に答える