77

苦痛で死なずに、極性化された枝へのマージの影響をどのように元に戻すことができますか?

この問題は何ヶ月も私を悩ませてきましたが、ついにあきらめました.

2 つの名前付きブランチを持つ 1 つのリポジトリがあります 。AとB。

A に発生する変更は、必然的に B にも発生します。

B で直接発生する変更は、A で発生してはなりません。

このような構成では、「B」を「A」にマージすると、B へのすべての変更が A で行われたかのように A に表示されるため、リポジトリで悲惨な問題が発生します。

この状況から回復する唯一の「通常の」方法は、マージを「バックアウト」することです。つまり、次のようになります。

 hg up -r A 
 hg backout -r BadMergeRev --parent BadMergerevBeforeOnA 

後で正しい方向にマージすることを決定するまでは、これはすべて問題なくダンディに見えますが、あらゆる種類の厄介なことが発生し、特にブランチ B で消去/コメントアウトされたコードが突然消去またはコメント解除されます。

これまでのところ、「それをやらせてから、すべての問題を手作業で修正する」以外に、これに対する実用的な解決策はありませんでした。

問題を明確にする画像を次に示します。

【原画消失】

ファイル C & E (または変更 C & E ) は、ブランチ a ではなく、ブランチ b にのみ表示される必要があります。ここのリビジョン A9 (ブランチ a、revno 9) が問題の始まりです。

リビジョン A10 と A11 は、「バックアウト マージ」フェーズと「バックアウト マージ」フェーズです。

また、リビジョン B12 は水銀的であり、ドロップしないように意図された変更を誤って繰り返しドロップしています。

このジレンマは多くのフラストレーションと青煙を引き起こしました。私はそれを終わらせたいと思っています。

ノート

フックまたはポリシーのいずれかを使用して、リバース マージが発生しないようにすることが明らかな答えかもしれませ。必然的にそれ起こると仮定して、それが起こったときにそれを解決できるようにします.

詳しく説明する

モデルでは、個別のファイルを使用しました。これらは問題を単純にします。これらは、別の行になる可能性のある任意の変更を表すだけです。

また、怪我に侮辱を加えるために、ブランチ A に実質的な変更があり、「ブランチ A の変更が、変更のように見える (そしてバックアウトされた) ブランチ B の変更と競合する」という問題が残ります。代わりにブランチ A で "

履歴書き換えのトリックについて:

これらすべての遡及ソリューションの問題は次のとおりです。

  1. 9000 件のコミットがあります。
  2. したがって、新たにクローニングするには30分かかります
  3. リポジトリの不良クローンがどこかに1 つでも存在すると、元のリポジトリに再び接触して、再びすべてをぶち壊す可能性があります。
  4. 誰もがこのリポジトリを既に複製しており、進行中のコミットで数日が経過しました。
  5. そのようなクローンの 1 つがたまたまライブ サイトであるため、「それを消去してゼロから始める」=「ビッグ ノノ」

(上記の多くは少しばかげていることは認めますが、私の制御の範囲外です)。

実行可能な唯一の解決策は、人々はすべて間違ったことをする可能性があり、そうするであろうこと、そしてこの間違いを「元に戻す」方法があることを前提とするものです。

4

5 に答える 5

50

悪いマージを永久に修正し、差分を手動でチェックする必要のない解決策を見つけたと思います。秘訣は、履歴をさかのぼって、悪いマージと並行してコミットを生成することです。

そのため、単一製品の維持されているバージョンごとに個別のブランチを持つリポジトリがあります。質問で提起された状況のように、以前のバージョンのブランチに加えられたすべての変更 (つまり、そのバージョンのバグ修正) は、最終的にすべて新しいバージョンのブランチにマージする必要があります。

具体的には、何かが BRANCH_V8 にチェックインされている場合、BRANCH_V9 にマージする必要があります。

現在、開発者の 1 人が次のような間違いを犯しています: 彼は BRANCH_V9 から BRANCH_V8 へのすべての変更をマージします (つまり、間違った方向へのマージ)。さらに、その悪いマージの後、彼は間違いに気付く前にいくつかの余分なコミットを実行します。

そのため、状況は以下のグラフィカルなログに示されているとおりです。

o BRANCH_V8 - 13 - 不適切なマージ直後の重要なコミット
| |
o BRANCH_V8 - 12 - BRANCH_V9 からの間違ったマージ
|\
| | o BRANCH_V8 - 11 - BRANCH_V8 に関するコメントを追加 (つまり、最後の既知の良好な状態)
| | | |
を | BRANCH_V9 - 10 - BRANCH_V9 の最後のコミット
| | | |

この間違いは次のように修正できます。

  1. ローカル ディレクトリを BRANCH_V8 の最後の良好な状態に更新します。hg update 11
  2. その最後の良好な状態の新しい子を作成します。
    1. 一部のファイルを変更します$EDITOR some/file.txt(Mercurial では空のコミットが許可されていないため、これが必要です)
    2. これらの変更をコミットしますhg commit -m "generating commit on BRANCH_V8 to rectify wrong merge from BRANCH_V9"
      。状況は次のようになります。
      o BRANCH_V8 - 14 - BRANCH_V8 でコミットを生成して、BRANCH_V9 からの間違ったマージを修正する
      | |
      | | o BRANCH_V8 - 13 - 不適切なマージ直後の重要なコミット
      | | | |
      | | o BRANCH_V8 - 12 - BRANCH_V9 からの間違ったマージ
      |/|
      を | BRANCH_V8 - 11 - BRANCH_V8 にコメントを追加
      | | | |
      | | o BRANCH_V9 - 10 - BRANCH_V9 の最後のコミット
      
  3. 新しく生成された head を、不適切なマージが発生したリビジョンとマージし、コミットする前にすべての変更を破棄します。2 つのヘッドを単純にマージしないでください。マージ後に発生した重要なコミットも失われます。

    1. merge : hg merge 12(競合を無視します)
    2. すべての変更を破棄します:hg revert -a --no-backup -r 14
    3. 変更をコミットします:hg commit -m "throwing away wrong merge from BRANCH_V9" 状況は次のようになります:
      o BRANCH_V8 - 15 - BRANCH_V9 から間違ったマージを破棄
      |\
      | | o BRANCH_V8 - 14 - BRANCH_V8 でコミットを生成して、BRANCH_V9 からの間違ったマージを修正する
      | | | |
      +---o BRANCH_V8 - 13 - 不適切なマージ直後の重要なコミット
      | | | |
      を | BRANCH_V8 - 12 - BRANCH_V9 からの間違ったマージ
      |\|
      | | o BRANCH_V8 - 11 - BRANCH_V8 にコメントを追加
      | | | |
      を | BRANCH_V9 - 10 - BRANCH_V9 の最後のコミット
      | | | |
      

    すなわち。BRANCH_V8 には 2 つのヘッドがあります。1 つは不適切なマージの修正を含み、もう 1 つはマージの直後に発生した BRANCH_V8 の残りの重要なコミットを含みます。

  4. BRANCH_V8 の 2 つのヘッドをマージします。
    1. マージ:hg merge
    2. 専念 :hg commit -m "merged two heads used to revert from bad merge"

BRANCH_V8 の最後の状況は修正され、次のようになります。

o BRANCH_V8 - 16 - 不適切なマージから復帰するために使用されるマージされた 2 つのヘッド
|\
| | o BRANCH_V8 - 15 - BRANCH_V9 から間違ったマージを破棄
| | |\
| | | | o BRANCH_V8 - 14 - BRANCH_V8 でコミットを生成して、BRANCH_V9 からの間違ったマージを修正する
| | | | | |
を | | | BRANCH_V8 - 13 - 不適切なマージ直後の重要なコミット
|/ /
を | BRANCH_V8 - 12 - BRANCH_V9 からの間違ったマージ
|\|
| | o BRANCH_V8 - 11 - BRANCH_V8 にコメントを追加
| | | |
を | BRANCH_V9 - 10 - BRANCH_V9 の最後のコミット
| | | |

これで、BRANCH_V8 の状況は正しくなりました。残っている唯一の問題は、BRANCH_V8 から BRANCH_V9 への次のマージが正しくないということです。これは、BRANCH_V9 では望ましくない悪いマージの「修正」でもマージされるためです。ここでのコツは、BRANCH_V8 から BRANCH_V9 に別々の変更でマージすることです。

  • BRANCH_V8 から BRANCH_V9 への最初のマージは、BRANCH_V8 での不適切なマージの前からの正しい変更です。
  • マージミスとその修正で 2 回目のマージを行い、何もチェックする必要がなく、すべての変更を破棄します
  • 3 番目に、BRANCH_V8 からの残りの変更をマージします。

詳細に:

  1. 作業ディレクトリを BRANCH_V9 に切り替えます。hg update BRANCH_V9
  2. BRANCH_V8 の最後の良好な状態 (つまり、不適切なマージを修正するために生成したコミット) でマージします。このマージは、通常のマージと同様のマージです。競合は通常どおりに解決する必要があり、何も破棄する必要はありません。
    1. マージ:hg merge 14
    2. commit :hg commit -m "Merging in last good state of BRANCH_V8" 現在の状況は次のとおりです。
      @ BRANCH_V9 - 17 - BRANCH_V8 の最後の良好な状態でのマージ
      |\
      | | | | o BRANCH_V8 - 16 - 不適切なマージから復帰するために使用されるマージされた 2 つのヘッド
      | | | | |\
      | | +---o BRANCH_V8 - 15 - BRANCH_V9 から間違ったマージを捨てる
      | | | | | | | |
      | | を | | | BRANCH_V8 - 14 - BRANCH_V8 でコミットを生成して、BRANCH_V9 からの間違ったマージを修正する
      | | | | | | | |
      | | | | を | BRANCH_V8 - 13 - 不適切なマージ直後の重要なコミット
      | | | | |/
      +---o BRANCH_V8 - 12 - BRANCH_V9 からの間違ったマージ
      | | |/
      | | o BRANCH_V8 - 11 - BRANCH_V8 にコメントを追加
      | | | |
      を | BRANCH_V9 - 10 - BRANCH_V9 の最後のコミット
      | | | |
      
  3. BRANCH_V8 の不適切なマージとその修正をマージし、すべての変更を破棄します。
    1. マージ:hg merge 15
    2. すべての変更を元に戻す:hg revert -a --no-backup -r 17
    3. マージをコミットします:hg commit -m "Merging in bad merge from BRANCH_V8 and its fix and throwing it all away" 現在の状況:
      @ BRANCH_V9 - 18 - BRANCH_V8 からの不適切なマージとその修正をマージし、すべて破棄する
      |\
      | | o BRANCH_V9 - 17 - BRANCH_V8 の最後の良好な状態でのマージ
      | | |\
      +-----o BRANCH_V8 - 16 - 悪いマージから戻すために使用される 2 つのヘッドのマージ
      | | | | | | | |
      o---+ | BRANCH_V8 - 15 - BRANCH_V9 から間違ったマージを捨てる
      | | | | | | | |
      | | | | を | BRANCH_V8 - 14 - BRANCH_V8 でコミットを生成して、BRANCH_V9 からの間違ったマージを修正する
      | | | | | | | |
      +-----o BRANCH_V8 - 13 - 悪いマージの直後の重要なコミット
      | | | | | |
      o---+ BRANCH_V8 - 12 - BRANCH_V9 からの間違ったマージ
      |/ /
      | | o BRANCH_V8 - 11 - BRANCH_V8 にコメントを追加
      | | | |
      を | BRANCH_V9 - 10 - BRANCH_V9 の最後のコミット
      | | | |
      
  4. BRANCH_V8 からの残りの変更をマージします。
    1. マージ:hg merge BRANCH_V8
    2. 専念 :hg commit -m "merging changes from BRANCH_V8"

最終的に、状況は次のようになります。

@ BRANCH_V9 - 19 - BRANCH_V8 からの変更のマージ
|\
| | o BRANCH_V9 - 18 - BRANCH_V8 からの不適切なマージとその修正をマージし、すべて破棄する
| | |\
| | | | o BRANCH_V9 - 17 - BRANCH_V8 の最後の良好な状態でのマージ
| | | | |\
を | | | | | BRANCH_V8 - 16 - 不適切なマージからの復帰に使用される 2 つのヘッドのマージ
|\| | | | |
| | o---+ BRANCH_V8 - 15 - BRANCH_V9 から間違ったマージを捨てる
| | | | | | | |
| | | | | | o BRANCH_V8 - 14 - BRANCH_V8 でコミットを生成して、BRANCH_V9 からの間違ったマージを修正する
| | | | | | | |
を | | | | | BRANCH_V8 - 13 - 不適切なマージ直後の重要なコミット
|/ / /
o---+ BRANCH_V8 - 12 - BRANCH_V9 からの間違ったマージ
|/ /
| | o BRANCH_V8 - 11 - BRANCH_V8 にコメントを追加
| | | |
を | BRANCH_V9 - 10 - BRANCH_V9 の最後のコミット
| | | |

差分を手動で確認する必要のないこれらのすべての手順の後、BRANCH_V8 と BRANCH_V9 は正しく、BRANCH_V8 から BRANCH_V9 への将来のマージも同様に正しくなります。

于 2010-01-19T11:46:42.393 に答える
2

ピンチでは、リポジトリを大量の diff にエクスポートし、履歴を編集してから、必要なものだけを新しいリポジトリに貼り付けることができるため、損傷のリスクはありません。あなたの例にとっては悪くないかもしれませんが、実際の歴史がどのように見えるかはわかりません。

より簡単な操作を実行しながら、このページを参照しました。

http://strongdynamic.blogspot.com/2007/08/expunging-problem-file-from-mercurial.html

于 2008-11-06T08:46:53.013 に答える
2

OK、壊れたリポジトリ (hg init) とは別のディレクトリに新しい空のリポジトリを作成することから始めます。ここで、最新の既知の正常なバージョンをプルアップして、新しいリポジトリに含めます。悪いマージをプル、その前にすべてをプルするようにしてください。古いリポジトリで、A の最新の既知の正常なバージョンに更新し、次の操作を行います。

hg graft r1 r2 r3

ここで、r1-3 は失敗したマージ後に行われた変更です。この時点で競合が発生する可能性があります。それらを修正します。

これにより、 A の最新の既知の正常なバージョンに対して新しい変更が生成されるはずです。これらの新しい変更を新しいリポジトリにプルします。何も見逃していないことを再確認するには、古いリポジトリに対して hg incoming を実行します。失敗したマージと r1-3 以外のものが表示された場合は、プルしてください。

古いリポジトリを破棄します。あなたは終わった。マージは新しいリポジトリにはまったくないので、履歴を書き換える必要はありませんでした。

于 2012-04-18T05:18:39.933 に答える
1

freenode の #mercurial に関する何人かの親切な人々との多くの議論の後、mpm は私のテスト ケースでうまくいくと思われる部分的な解決策を提供しました (私はシナリオを複製しようとして偽のリポジトリを生成しました)。

ただし、私の実際のリポジトリでは、理由がよくわかりませんが、まだ完全ではありません。

この問題を解決するために現在提案されている方法の図を次に示します。

【原画消失】

修正する問題は少なくなりましたが、差分を比較し (つまり、 b46:b11 対 b46:b8 、 a43:a10 対 a43:a9 )、いくつかの変更を手動で編集する必要があります。

どのリポジトリでも機能する保証された方法が得られるまで、この質問を閉じたり答えたりしないでください。

重要

このようなことをしようとしている人は、リポジトリを複製して、最初にサンドボックスのように遊んでください。マージ プロセスで行うべきことと同じように、失敗した場合は破棄してやり直すことができます。

于 2008-11-06T20:32:25.990 に答える
1

B から A に変更セットをいくつかマージしたいですか? あなたが行ってきたように変更セットを取り消すことは、あなたがすでに苦しんでいるので、本当に悪い考えです.

移植拡張機能を使用するか、共通の変更を加えて A と B の両方にマージする 3 番目のブランチを用意する必要があります。

于 2008-11-06T18:39:54.207 に答える