Я считаю, что проблема в том, что слияния работают не так, как вы думаете.Вы пишете
Поскольку новая ветвь выпуска содержит все наборы изменений ветви функций (ничего не отменено), почему ветвь по умолчанию также не получает все эти наборы изменений?
Когда вы объединяете две ветви, неправильно думать, что они применяют все изменения из одной ветви в другую.Таким образом, ветвь default
не "получает" никаких изменений от release2
.Я знаю, что мы обычно так думаем о слияниях, но это неточно.
Что действительно происходит при слиянии двух наборов изменений, так это:
Mercurial находит общего предкадля двух наборов изменений.
Для каждого файла, который отличается между двумя наборами изменений, Mercurial запускает трехстороннее объединение алгоритм с использованием файла предкафайл в первом наборе изменений и файл во втором наборе изменений.
В вашем случае вы объединяете редакцию 11 и 12. Наименее общий предок - редакция 8. Это означает, чтоMercurial запустит трехстороннее слияние версий файлов оттуда:
Inтрехстороннее слияние, изменения всегда козыри без изменений.Mercurial видит, что файлы были изменены между 8 и 11, и не видит изменений между 8 и 12. Таким образом, он использует измененную версию из ревизии 11 в слиянии.Это относится к любому трехстороннему алгоритму слияния.Полная таблица слияния выглядит следующим образом, где old
, new
, ... - содержимое соответствующих блоков в трех файлах:
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)
Боюсь, что changege merge changesetне следует отказываться от вообще из-за этого удивительного поведения слияния.Mercurial 2.0 и более поздние версии прервут и будут жаловаться, если вы попытаетесь отказаться от слияния.
В общем, можно сказать, что трехсторонний алгоритм слияния предполагает, что все изменения хороши .Поэтому, если вы объедините 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 не позволит вам выбрать собственную базовую ревизию при слиянии , алгоритм трехстороннего слияния не позволит вам передумать относительно возврата.
Что вы можете сделать, однако, откатить назад .Это означает, что вы повторно вводите изменения из вашей функциональной ветви в свою ветку релиза.Итак, вы начинаете с графика, подобного
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
После этого второго возврата вы можете снова объединиться с 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
.Это означает, что единственными изменениями, которые необходимо учитывать при трехстороннем объединении, являются изменения между a1
и a2
и a1
и b2
.Здесь b2
уже содержит основную часть изменений "в" a2
, поэтому слияние будет небольшим.