Меркуриальное слияние выбрало неправильные изменения, каков правильный способ исправить это?

Были внесены изменения в наш .vcproj, чтобы исправить проблему на машине сборки (changeet 1700). Позже разработчик объединил свои изменения (изменения с 1710 по 1715) в багажник, но меркурийное авто-слияние переписало изменения с 1700 года. Я предполагаю, что это произошло потому, что он выбрал неправильную ветвь как "родителя" слияния (см. Часть 2 вопроса).

1) Что такое "правильный" меркурийный способ исправить эту проблему, учитывая, что из всех объединенных файлов только один файл был скомбинирован неправильно, а

2) что должен сделать разработчик по-другому, чтобы убедиться, что этого не произошло? Существуют ли способы принудительного применения "правильного" способа?

Изменить: я, вероятно, не совсем понял, что произошло. Разработчик А изменил строку в нашем .vcproj файле, который удалил опцию для компилятора. Его регистрация стала изменением 1700. Разработчик B, работающий от предыдущего родителя (скажем, changeet 1690), внес некоторые изменения в совершенно разные части проекта, но он касался файла .vcproj(только не где-то рядом с внесенными изменениями разработчиком A). Когда разработчик B объединил свои изменения (изменившись с 1710 по 1715), процесс слияния переписал изменения с 1700.

Чтобы исправить это, я только что повторно модифицировал файл .vcproj, чтобы снова включить изменение, и проверил его. Я просто хотел знать, почему Mercurial считал, что он не должен сохранять изменения в 1700 году и независимо от того, был "официальный" способ исправить это.

Отредактируйте второе: разработчик B ругается вверх и вниз, что Mercurial объединил файл .vcproj, не требуя разрешения конфликта, но, конечно же, возможно, что он просто забывает, и в этом случае все это упражнение является академическим.

Ответ 1

Сначала рассмотрю вторую часть вашего вопроса...

Если есть конфликт, автоматические инструменты слияния должны заставить программиста решить, как происходит слияние. Но общее предположение состоит в том, что конфликт будет включать два изменения в один и тот же набор строк. Если какой-то конфликт возникает из-за изменений в строках, которые не близки друг к другу, автоматическое слияние будет blithely выбирать оба изменения, и появится ошибка.

Общий случай инструмента слияния, который всегда сливается должным образом, очень трудно решить, и на самом деле не может быть с текущей технологией. Вот пример того, что я имею в виду из C:

int i;  // Someone replaces this with 'short i' in one changeset stating
        // that a short is more efficient.

// ...  lots of code;

// Someone else replaces all the 65000s with 100000s in another changeset,
// saying that more precision is needed.
for (i = 0; i < 65000; ++i) {
    integral_approximation_piece(start + i/65000.0, end + (i + 1) / 65000.0);
}

Никакой инструмент слияния не поймает этот конфликт. Инструмент должен был бы фактически скомпилировать код, чтобы увидеть, что эти две части кода имеют какое-либо отношение к eachother, и хотя этого, вероятно, будет достаточно в этом случае, я могу построить пример, который потребует запуска кода и результаты, рассмотренные, чтобы поймать конфликт.

Это означает, что то, что вы действительно должны делать, - это строго проверить ваш код после слияния, как и после любых других изменений. Подавляющее большинство слияний приведет к очевидным конфликтам, которые разработчик должен будет решить (хотя это разрешение часто довольно очевидно) или будет сливаться чисто. Но очень немногие слияния, которые не соответствуют ни одной из категорий, нелегко обрабатывать автоматически.

Это также может быть устранено методами развития, которые поощряют местность. Например, стандарт кодирования, который гласит: "Переменные должны быть объявлены рядом с тем, где они используются".

Я предполагаю, что файлы .vcproj особенно подвержены этой проблеме, поскольку разработчики не очень хорошо понимают их, и поэтому, если возникают конфликты, они не будут знать, что с ними делать. Я предполагаю, что это произошло, и ваш разработчик просто вернулся к ревизиям, которые он проверил.

Что касается части 1...

Что делать в этом случае, зависит от вашего процесса разработки. Вы можете отключить набор изменений слияния и повторить его, хотя это не сработает очень хорошо, если многие люди уже потянули его, и он будет работать особенно плохо, если есть много изменений, которые уже были проверены на основе в наборе изменений слияния.

Вы также можете проверить новое изменение, которое устраняет проблему с помощью слияния.

Это в основном ваши два варианта.

Тон вашего сообщения, как мне кажется, указывает, что у вас может быть какая-то политика, связанная с этой проблемой в вашей организации, и люди обвиняют эту ошибку в частых слияниях Mercurial. Поэтому я укажу, что любая система управления изменениями может иметь эту проблему. В случае Subversion, например, каждый раз, когда разработчик выполняет обновление, в то время как у них есть выдающиеся изменения в рабочем каталоге, они выполняют слияние, и такая проблема может возникнуть с любым слиянием.

Ответ 2

В меркуриальном объединении нет ни одного родителя, он по определению имеет двух и только двух родителей. Когда кто-то сливается, они делают два варианта:

  • Какие два набора изменений составят два изменения.
  • Какой из этих наборов изменений будет левым родителем и который будет правильным родителем

Из этих двух вопросов первое очень важно, а второе едва ли имеет значение, хотя мне потребовалось некоторое время, чтобы понять это.

Вы выбираете левого родителя с помощью hg update X. Это изменяет вывод hg parents (или в новых версиях hg summary) и по существу определяет, что в вашем рабочем каталоге перед слиянием.

Вы выбираете правого родителя с помощью hg merge Y. Это говорит о слиянии X (родитель рабочего каталога) с набором изменений Y. В качестве особого случая, если в вашем репозитории есть только две главы, а ваш родитель уже является одним из них, тогда Y будет по умолчанию другим.

Мне нужно было бы увидеть ваш итоговый граф, чтобы узнать, что сделал разработчик, но возможно, что он не обновлялся до той или иной главы, прежде чем вызывать слияние, что позволило бы ему объединить одну голову с какой-то точкой в ​​истории.

Если ваш разработчик выбрал правильных родителей для слияния, то левое и правое не имеет большого значения - единственное реальное различие заключается в том, что при использовании hg diff или hg log -p или какой-либо другой команды, которая показывает патч для набора изменений слияния он отображается относительно левого родителя. Это, однако, в основном фактор отображения. Функционально они в значительной степени идентичны.

Предполагая, что ваш разработчик выбрал нужные изменения, то то, что он должен был сделать, это проверить результат слияния, прежде чем совершать его. Слияние - это разработка программного обеспечения, а не раздражающий побочный эффект VCS, а не тестирование перед фиксацией - это ошибка.

Закрепление

Чтобы исправить это, просто выполните повторное слияние. Используйте hg update для установки одного родителя, используйте hg merge, чтобы выбрать другой. Убедитесь, что ваш текущий рабочий каталог верен, а затем зафиксирован. Вы можете избавиться от его плохого слияния, используя что-то вроде hg strip или лучше, просто закройте его ветку с помощью hg commit --close-branch после обновления к ней.

Как избежать

Вы говорите "меркуриальное автоматическое слияние", но mercurial действительно не сжимается автоматически. Он делает premerge, который представляет собой чрезвычайно осторожную комбинацию очевидных изменений, но он настолько осторожен, что даже не будет сливаться для вас, если каждый родитель слияния добавит код в том же регионе, потому что он не может знать, какой блок кода вы используете, скорее всего, сначала.

Вы можете полностью отключить эту премьеру или по файлу с помощью параметров конфигурации инструмента слияния:

https://www.mercurial-scm.org/wiki/MergeToolConfiguration?highlight=premerge