問題は、マージの動作があなたが思っているものとは異なることだと思います。あなたが書く
新しいリリースブランチにはすべての機能ブランチチェンジセットが含まれているため(バックアウトされていないものはありません)、デフォルトブランチがこれらのチェンジセットのすべてを受け取らないのはなぜですか?
2つのブランチをマージする場合、あるブランチから別のブランチにすべての変更を適用すると考えるのは誤りです。したがって、default
ブランチはから変更セットを「受信」しませんrelease2
。これが私たちが通常マージについて考える方法であることを私は知っていますが、それは不正確です。
2つのチェンジセットをマージすると、実際に何が起こるかは次のとおりです。
Mercurialは、2つのチェンジセットの共通の祖先を見つけます。
Mercurialは、2つのチェンジセット間で異なるファイルごとに、祖先ファイル、最初のチェンジセット内のファイル、および2番目のチェンジセット内のファイルを使用して3方向マージアルゴリズムを実行します。
あなたの場合、リビジョン11と12をマージしています。最も一般的でない祖先はリビジョン8です。これは、Mercurialがそこのリビジョンのファイル間で3方向のマージを実行することを意味します。
3者間マージでは、変更は常に変更よりも優先されます。Mercurialは、ファイルが8から11の間で変更されていることを確認し、8から12の間で変更がないことを確認します。したがって、マージではリビジョン11から変更されたバージョンを使用します。これは、すべての3方向マージアルゴリズムに適用されます。完全なマージテーブルは次のようになります。ここold
でnew
、、、...は3つのファイル内の一致するハンクのコンテンツです。
ancestor local other -> merge
old old old old (nobody changed the hunk)
old old new new (they changed the hunk)
old new old new (you changed the hunk)
old new new new (hunk was cherry picked onto both branches)
old foo bar <!> (conflict, both changed hunk but differently)
この驚くべきマージ動作のために、マージチェンジセットをバックアウトするべきではないのではないかと心配しています。Mercurial 2.0以降では、マージをバックアウトしようとすると中止され、文句が表示されます。
一般に、3方向マージアルゴリズムは、すべての変更が適切であると想定していると言えます。したがって、マージbranch1
してdev
から、後でバックアウトを使用してマージを元に戻すと、マージアルゴリズムは、状態が以前よりも「良好」であると見なします。これは、バックアウトされた変更を元に戻すために、後で再マージすることはできないことを意味しますbranch1
。dev
にマージするときに「ダミーマージ」を使用することができますdefault
。マージするだけで、マージ先のリリースブランチからの変更を常に保持しますdefault
。
$ hg update default
$ hg merge release2 --tool internal:other -y
$ hg revert --all --rev release2
$ hg commit -m "Release 2 is the new default"
それは問題を回避し、力default
はのようになりrelease2
ます。default
これは、リリースブランチにマージされない限り、変更がまったく行われないことを前提としています。
スキップされた機能を使用してリリースを作成できる必要がある場合、「正しい」方法は、それらの機能をまったくマージしないことです。マージは強力なコミットメントです。マージチェンジセットには、両方の祖先からのすべての優れた機能が含まれていることをMercurialに伝えます。Mercurialがマージ時に独自のベースリビジョンを選択できない限り、3方向マージアルゴリズムではバックアウトについての考えを変えることはできません。
ただし、できることは、バックアウトをバックアウトすることです。これは、機能ブランチからリリースブランチに変更を再導入することを意味します。だからあなたは次のようなグラフから始めます
release: ... o --- o --- m1 --- m2
/ /
feature-A: ... o --- o /
/
feature-B: ... o --- o --- o
ここで、A機能が不良であると判断し、マージを取り消します。
release: ... o --- o --- m1 --- m2 --- b1
/ /
feature-A: ... o --- o /
/
feature-B: ... o --- o --- o
次に、別の機能をリリースブランチにマージします。
release: ... o --- o --- m1 --- m2 --- b1 --- m3
/ / /
feature-A: ... o --- o / /
/ /
feature-B: ... o --- o --- o /
/
feature-C: ... o --- o --- o --- o --- o
A機能を再導入したい場合は、バックアウトできますb1
。
release: ... o --- o --- m1 --- m2 --- b1 --- m3 --- b2
/ / /
feature-A: ... o --- o / /
/ /
feature-B: ... o --- o --- o /
/
feature-C: ... o --- o --- o --- o --- o
デルタをグラフに追加して、何がいつどこで変化するかをより適切に示すことができます。
+A +B -A +C --A
release: ... o --- o --- m1 --- m2 --- b1 --- m3 --- b2
この2回目のバックアウトの後、feature-A
新しいチェンジセットが追加された場合に備えて、再度マージできます。マージするグラフは次のようになります。
release: ... o --- o --- m1 --- m2 --- b1 --- m3 --- b2
/ / /
feature-A: ... o -- a1 - a2 / /
/ /
feature-B: ... o --- o --- o /
/
feature-C: ... o --- o --- o --- o --- o
そして、あなたはマージa2
しb2
ます。共通の祖先はになりますa1
。つまり、3者間マージで考慮する必要がある変更は、a1
anda2
とa1
andの間の変更だけですb2
。ここb2
にはすでに変更の大部分が「含まれている」a2
ので、マージは小さくなります。