web-dev-qa-db-ja.com

Mercurialでマージをバックアウトし、後でそのブランチと再マージするにはどうすればよいですか?

Defaultとbranch1の2つのブランチがあります。誤って、チームの1人がブランチ1をデフォルトにマージしました。 branch1のコンテンツは、デフォルトとマージする準備がまだできていません(ビルドとデプロイ環境の大幅な修正が含まれています)。

「hg backout」を使って実験を行い、マージをバックアウトしました(これが正しい方法かどうかはわかりません)。次に、branch1からの変更はデフォルトで削除されます。これは問題ありませんが、branch1と再マージすることはできません。

この問題をどのように解決すればよいですか?

54
Peter Moberg

ここには、これを実行するシナリオがたくさんあります。それぞれのシナリオを見出しにして、自分のケースに適したシナリオを見つけられるようにします。 Mercurialはまだ学習中であることに注意してください。私が言いたいことが間違っていたり、間違った用語を使用したりすると、より良い結果が得られる場合などに、ポインタが必要です。

これ以上の変更はありません、マージは共有されません(プッシュ/プルはありません)

プログラマはマージしましたが、他には何もしていません。また、変更を誰かと共有していません

この場合、単にローカルクローンを破棄し、安全なリポジトリから新しいクローンを取得します。

マージではなくローカルでの変更、共有されない

プログラマはマージし、そのマージに基づいて作業を続けました。マージ後のチェンジセットは保持する必要がありますが、マージ自体は削除する必要があります。変更(マージ+次のチェンジセット)は誰とも共有していません

この場合、次の4つのうちの1つを行います。

  1. REBASE拡張を使用してみてください。これにより、変更セットが1つの場所から別の場所に移動します。変更セットがマージで導入されたコード変更に基づいている場合は、違いを調整するためにいくつかの手動作業を行う必要があります。
  2. MQ拡張機能を使用して、パッチキューに保持するチェンジセットをプルしてから、別の場所にプッシュして戻します。ただし、これはマージに基づく変更の点でREBASE拡張と同じ問題になります。
  3. TRANSPLANT拡張機能を使用して、ある場所から別の場所に変更を「コピー」してみてください。それでも、最初の2つと同じ問題が存在します。
  4. おそらく、差分ツールを使用して作業をやり直し、破棄したいチェンジセットで行われた変更を取得して、正しい場所で再度実行します。

マージ変更セット+以下のすべての変更セットを取り除くには、いくつかのオプションがあります:

  1. MQ拡張機能でstripコマンドを使用する

    hg strip <hash of merge changeset>
    
  2. クローンを作成してプルし、マージに至るまでのチェンジセットのハッシュを指定します。本質的には、損傷したクローンを新しいクローンにプルして新しいクローンを作成し、不要なマージをプルしないようにします。

    hg clone damaged -r <hash of first parent> .
    hg pull damaged -r <hash of second parent>
    

マージは他の人にプッシュされ、クローンを制御します

プログラマがマスターリポジトリにプッシュしたか、他の誰かにプッシュしたか、誰かがプログラマリポジトリからプルしました。ただし、(開発者のグループのように)あなたはすべてのリポジトリを制御できます。たとえば、さらに作業が完了する前に全員に連絡して話しかけることができます

この場合、手順1または2を実行できるかどうかを確認しますが、多くの場所で実行する必要がある可能性があるため、これには多くの作業が含まれる可能性があります。

誰もマージチェンジセットに基づいて作業を行っていない場合は、手順1または2を使用してクリーンアップしてから、マスターリポジトリにプッシュし、マスターリポジトリから新しいクローンを取得するように全員に依頼します。

マージがプッシュされました。クローンを制御できません

プログラマがマージセットをプッシュしましたが、誰がマージチェンジセットを持つかわかりません。言い換えると、それをyourリポジトリから根絶することに成功した場合、それをまだ持っている誰かからの迷惑なPushがそれを取り戻します。

マージチェンジセットを無視して、2つのブランチで、それが起こらなかったかのように作業します。これにより、ぶら下がりの頭が残ります。その後、2つのブランチをマージしたときに、このヘッドをnullマージして、それを取り除くことができます。

  M         <-- this is the one you want to disregard
 / \
*   *
|   |
*   *
|   |

2つのブランチで作業を続けるだけです。

|   |
*   *
| M |       <-- this is the one you want to disregard
|/ \|
*   *
|   |
*   *
|   |

その後、2つをマージし、実際にマージします。

  m
 / \
*   *
|   |
*   *
| M |       <-- this is the one you want to disregard
|/ \|
*   *
|   |
*   *
|   |

次に、ヌルマージを実行して、ぶら下がりの頭を取り除くことができます。残念ながら、TortoiseHg以外でそれを行う方法はわかりません。ブランチの1つからの変更を破棄できるチェックボックスがあります。

TortoiseHgを使用して、保持するマージ(最上位の小文字のm)に更新し、下のぶら下がりマージヘッドを選択して右クリックし、[マージターゲット(その他)リビジョンからのすべての変更を破棄する]をオンにします。 : discard changes from target

「hg backout」を使って実験を行い、マージをバックアウトしました(これが正しい方法かどうかはわかりません)。次に、branch1からの変更はデフォルトで削除されます。これは問題ありませんが、branch1と再マージすることはできません。

マージのキャンセルにはバックアウトを使用します。再マージすることはできませんが、「バックアウトマージをバックアウト」することはできます。つまり、再マージが必要な場合は、「バックアウトされたマージチェンジセット...」で「hgバックアウト」をコミットしてから、ブランチを再度マージします。

例:

  7     M       remerge
  6   /   \
  5   *   |     hg backout 3 (backout backout)
  4   |   *     fix error 
  3   *   |     hg backout 2
  2   M   |     fail merge
    /     \
  1 *     *
    |     |
4

たくさんのご意見をいただき、ありがとうございました!私たちは問題を解決するために急いでいたので、私たちのグループはMercurialに対して比較的新しいので、非常に実用的なソリューションを使用しました。

リポジトリサーバーで新しいリポジトリを作成し、マージの直前のリビジョンまで古いリポジトリのクローンを作成しました。次に、新しいクローンをサーバーにプッシュし、新しいリンクを全員に送信しました。幸い、私たちは非常に小さな開発チームです。

おそらく、問題を解決するための最もコッシュな方法ではありませんが、それはうまくいきました:)

1
Peter Moberg

この回答は、あなたがすでにプッシュしていることを前提としています

これは、あなたが忘れたものに応じて、(少なくとも1つの)未解決の頭をもたらします。誰がどのブランチからプッシュしたかによります。

私はHGが大好きで熱心に使用していますが、彼らのブランチのアイデアは、(意図的に)不変である履歴と結び付けられていると、誰かをうまく動かすことができます。

私は通常、ブランチマージを行う前に、リポジトリのバックアップを(ローカルで)クローンします。これは、このためです。引っ張る前にいつもチェックしています。

エリック・レイモンド 何かに取り組んでいます それは多かれ少なかれDVCSにとらわれず、あなたが説明したようなおっと同様の状況で(うまくいけば)助けることができますが、HGサポートを完全に実装するつもりはないと思いますもう一週間か二週間。それでも、一見の価値があるかもしれません。

しかし、誰も「おっとっと」チップを引いていない場合にのみ役立ちます。

0
Tim Post

マージをうまくバックアウトすることはできません。 IMO、これを処理する最良の方法は、マージを中止し、マージ前の変更セットのストランドを続行して、ダングリングヘッド(ストリップ可能)を残すことです。マージ後に他の変更が発生した場合、それらは新しい「良い」ヘッドに再ベースできます。

0
Ringding

私はこの正確な問題を抱えていました。同僚が誤って私のブランチをデフォルトのブランチにマージしましたが、まだ完了していません。最初は、ブランチをマージしてデフォルトのkeepsにしたいまで、うまく機能しているように見えるマージをバックアウトしました。必要なファイルがマージ時に削除対象としてマークされていました。

解決策は、同僚のミスを修正した元のバックアウトに戻り、それをバックアウトすることでした。これにより、ファイルが削除済みとしてマークされなくなり、ブランチをデフォルトにマージできるようになりました。

0
Justin