Слияние

Там, где ответвления используются для обеспечения отдельных линий разработки, на некоторой стадии возникает необходимость произвести слияние сделанных в одном из ответвлений изменений со стволом, или наоборот, ствола с ответвлением.

Важно понимать, как слияние и ветвление работают в Subversion перед началом их использования, так как этот процесс может стать довольно сложным. Настоятельно рекомендуется прочитать главу Branching and Merging (Ветвление и слияние) в Книге о Subversion, которая содержит полное описание и множество примеров использования.

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

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

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

Слияние с диапазоном ревизий

Этот метод применяется в случае, когда вы сделали одну или несколько ревизий в ответвлении (или в основном стволе) и желаете перенести эти изменения и в другое ответвление.

Получается, что в этой ситуации вы предписываете Subversion выполнить следующее: «Вычисли изменения, необходимые, чтобы [ОТ] ревизии 1 ответвления А перейти [ДО] ревизии 7 ответвления А, и примени эти изменения к моей рабочей копии (относящейся к стволу или ответвлению Б).»

Воссоединение с ответвлением

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

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

После слияния вся разработка из ответвления полностью слита обратно с основной линией разработки. Ответвление теперь избыточно и может быть удалено.

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

Слияние двух различных деревьев

Это более общий случай метода воссоединения. Вы предписываете Subversion выполнить следующее: «Вычисли изменения, необходимые, чтобы [ОТ] ведущей ревизии ствола перейти [ДО] ведущей ревизии ответвления, и примени эти изменения к моей рабочей копии (относящейся к стволу).» В конечном итоге ствол будет выглядеть точно так же, как и ответвление.

Если ваш сервер/хранилище не поддерживают отслеживание слияний, то это единственный способ произвести слияние ответвления обратно в ствол. Другой типичный случай использования возникает при использовании ответвлений для кода сторонних производителей (vendor branches), когда вам необходимо произвести слияние изменений, возникающих после появления новой версии стороннего кода, с вашим кодом в стволе. Для дополнительной информации прочтите раздел об ответвлениях для кода сторонних производителей в Книге о Subversion.

Слияние с диапазоном ревизий

Рисунок 4.36. Мастер слияния - выбор диапазона ревизий

Мастер слияния - выбор диапазона ревизий


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

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

Важно

Существует важное отличие в способе указания диапазона ревизий между TortoiseSVN и клиентом командной строки. Наиболее лёгкий метод представить это - вообразить ограду со столбиками и пролётами.

В клиенте командной строки вы указываете изменения для слияния при помощи двух ревизий - «столбиков ограды», которые задают точки до и после.

В TortoiseSVN вы указываете набор изменений для слияния при помощи «пролётов ограды». Причина этого становится понятной при использовании диалога журнала для указания ревизий для слияния, где каждая ревизия выглядит как набор изменений.

Если вы производите слияние ревизий большими кусками, показанный в Книге о Subversion метод предполагает, что вы сливаете ревизии 100-200 в первый заход и 200-300 в следующий. В TortoiseSVN вы сливаете 100-200 сначала и 201-300 потом.

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

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

Если вы желаете произвести обратное слияние изменений, т.е. убрать из рабочей копии изменения, которые уже были зафиксированы, выберите ревизии, которые надо убрать, и убедитесь, что флажок Обратное слияние отмечен.

Если вы уже производили слияние некоторых изменений из этого ответвления, будем надеется, вы сделали заметку в сообщении журнала о последней ревизии, участвовавшей в слиянии, при фиксации изменений. В этом случае вы можете воспользоваться кнопкой Журнал для рабочей копии, чтобы обнаружить это сообщение. Используйте конечную точку в последнего слияния как начальную точку в новом. Например, если вы в последний раз сливали ревизии с 37 по 39, тогда начальной точкой для текущего слияния должна стать ревизия 40.

Если вы используете возможности Subversion по отслеживанию слияний, вам не нужно запоминать, какие ревизии уже были слиты - это для вас регистрирует Subversion. Если оставить диапазон ревизий пустым, то в слиянии будут участвовать все пока ещё не слитые ревизии. Прочтите «Отслеживание слияний» для того, чтобы узнать об этом больше.

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

Нажмите Далее и перейдите к «Параметры слияния»

Воссоединение с ответвлением

Рисунок 4.37. Мастер слияния - воссоединительное слияние

Мастер слияния - воссоединительное слияние


Для того, чтобы произвести слияние ответвления новой функции обратно со стволом, вы должны запустить мастер слияния из рабочей копии, извлечённой из ствола.

В поле Исходный URL: введите полный URL папки ответвления, которую вы желаете слить обратно со стволом. Вы также можете нажать ... для просмотра хранилища.

Несколько условий воссоединительного слияния. Для начала, сервер должен поддерживать отслеживание слияний. Рабочая копия должна быть с бесконечной глубиной извлечения (без разреженных извлечений), и в ней не должно быть локальных изменений, переключенных элементов, или элементов, обновлённых до ревизий, отличных от ведущей. Все изменения, произведённые в столе за время разработки в ответвлении, должны быть слиты обратно в ответвление (или помечены как слитые). Диапазон ревизий для слияния будет вычислен автоматически.

Слияние двух различных деревьев

Рисунок 4.38. Мастер слияния - слияние деревьев

Мастер слияния - слияние деревьев


Если вы используете этот метод для слияния ответвления новой функции обратно со стволом, то вам необходимо запустить мастер слияния из рабочей копии, извлечённой из ствола.

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

В поле До: введите полный URL папки с ответвлением новой функции.

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

Для выбора ревизии вы также можете использовать кнопку Журнал.

Параметры слияния

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

Вы можете указать глубину охвата, применяемую для слияния, т.е. насколько глубоко слияние должно затрагивать рабочую копию. Используемые термины для глубины охвата описаны в «Глубина извлечения». Глубина по умолчанию - Рабочая копия, использующая существующие установки глубины, что почти всегда является тем, что вам нужно.

В большинстве случаев вам необходимо, чтобы слияние учитывало историю файла, с тем чтобы сливались только изменения относительно общего предка. Иногда вам необходимо произвести слияние файлов, которые возможно и связаны, но не в вашем хранилище. Например, вы импортировали версии 1 и 2 сторонней библиотеки в две различные папки. Несмотря на то, что они логически связаны, Subversion об этом не знает, потому что видит только импортированные вами архивы. Если вы попытаетесь произвести слияние различий между двумя этими деревьями, вы увидите полное удаление с последующим полным добавлением. Для того, чтобы в Subversion использовались различия, основанные только на пути, вместо различий, основанных на истории, отметьте флажок Игнорировать предков. Больше прочитать на эту тему можно в Книге о Subversion Noticing or Ignoring Ancestry (Учитывание или игнорирование предков).

Вы можете задать способ обработки изменений завершений строк и пробельных символов. Эти параметры описаны в «Параметры сравнения завершений строк и непечатаемых знаков». Поведение по умолчанию - считать все различия в завершениях строк и пробельных символах реальными изменениями, которые должны быть слиты.

Флажок Принудительное слияние используется для избежания конфликта деревьев, в котором поступающее удаление затрагивает файл, который или изменён локально, или вообще не является версированным. Если удалить этот файл, то нет способа его восстановить, и поэтому этот флажок по умолчанию выключен.

Если вы используете отслеживание слияний, и вы желаете пометить ревизию как уже слитую, не выполняя слияние на самом деле, отметьте флажок Только зарегистрировать слияние. Сделать это вам может понадобится по двум причинам: случается, что слияние является слишком сложным для алгоритма слияния, поэтому вы производите нужные изменения вручную, а потом помечаете изменение (ревизию) как уже слитое, чтобы алгоритм слияния был об этом осведомлён. Или вы не желаете, чтобы определённая ревизия участвовала в слиянии. Пометив её как уже слитую, вы предотвратите слияние, если оно будет производиться клиентами, умеющими работать с информацией по отслеживанию слияний.

Now everything is set up, all you have to do is click on the Merge button. If you want to preview the results Test Merge simulates the merge operation, but does not modify the working copy at all. It shows you a list of the files that will be changed by a real merge, and notes files where conflicts may occur. Because merge tracking makes the merge process a lot more complicated, there is no guaranteed way to find out in advance whether the merge will complete without conflicts, so files marked as conflicted in a test merge may in fact merge without any problem.

Диалог выполнения слияния показывает каждый этап слияния, с указанием вовлечённых диапазонов ревизий. При этом в диапазоне может быть показано на одну ревизию больше, чем вы могли бы ожидать. Например, если вы указали произвести слияние ревизии 123, в диалоге выполнения будет написано «Слияние с ревизиями с 122 по 123». Для понимания этого вам нужно помнить, что слияние тесно связано с различиями. Процесс слияния работает путём создания списка различий между двумя точками в хранилище с последующим применением этих различий к вашей рабочей копии. Диалог выполнения просто показывает начальные и конечные точки для получения различий.

Просмотр результатов слияния

Теперь слияние выполнено. Хорошей мыслью будет посмотреть на результаты слияния и проверить, прошло ли оно так, как ожидалось. Слияние обычно бывает довольно замысловатым; конфликты часто возникают, если ответвление далеко отошло от ствола.

Для клиентов и серверов Subversion версий меньше 1.5, информация о слиянии не сохранялась и слитые ревизии надо было отслеживать вручную: когда вы проверили изменения и собираетесь фиксировать эту ревизию, в вашем сообщении при фиксации всегда должны быть указаны номера ревизий, которые вы перенесли в этом слиянии. Если вы позже пожелаете произвести ещё одно слияние, вам будет необходимо знать, что вы уже сливали, поскольку вам не нужно переносить изменения более одного раза. К сожалению, информацию о слияниях Subversion не ведёт. Дополнительная информация об этом содержится в Best Practices for Merging (Слияние. Лучший опыт) в Книге о Subversion.

Если ваш сервер и все клиенты Subversion версии 1.5 или больше, система отслеживания слияний будет регистрировать слитые ревизии и позволит избежать ситуации, когда ревизия сливается более одного раза. Это делает вашу жизнь намного проще, поскольку вы можете просто производить каждый раз слияние всего диапазона ревизий и знать, что только новые ревизии действительно будут слиты.

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

Подсказка

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

Важно

Subversion не может производить слияние файла с папкой и наоборот - только папки с папками и файлы с файлами. Если вы откроете диалог слияния для файла, тогда вы должны указать в нём путь к файлу. Если вы вызовите диалог для папки, тогда вы должны указать для слияния URL папки.

Отслеживание слияний

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

  • Вы можете избежать опасности слияния одной и той же ревизии дважды (проблема повторного слияния). Как только ревизия получает пометку о том, что она уже сливалась, последующие слияния, содержащие в своём диапазоне эту ревизию, будут её пропускать.

  • При слиянии ответвления обратно в ствол, в диалоге журнала могут быть показаны фиксации в ответвлении как часть журнала ствола, что позволяет лучше отслеживать изменения.

  • Когда вы вызываете окно журнала из диалога слияния, уже слитые ревизии отображаются серыми.

  • При показе информации об авторстве для файла можно выбрать, чтобы показывался первоначальный автор из слитых ревизий, а не тот, кто произвёл слияние.

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

Информация по отслеживанию слияний регистрируется в свойстве svn:mergeinfo клиентом при проведении слияния. Когда слияние фиксируется, сервер регистрирует эту информацию в базе данных, и при запросе журнала, а также информации о слиянии или об авторстве сервер сможет предоставить соответствующие данные. Для того, чтобы система работала правильно, вы должны убедиться, что сервер и все клиенты обновлены до необходимых версий. Более ранние клиенты не регистрировали информацию в свойстве svn:mergeinfo, а более ранние серверы не предоставляли информацию, запрашиваемую новыми клиентами.

Больше узнать об отслеживании слияний можно из документации об отслеживании слияний Subversion.

Обработка конфликтов, возникающих при слиянии

Слияние не всегда проходит гладко. Иногда возникает конфликт, и, если вы производите слияние нескольких диапазонов, обычно вы желательно уладить конфликт до начала слияния со следующим диапазоном. TortoiseSVN помогает вам в этом процессе, отображая диалог обратного вызова 'конфликты при слиянии'.

Рисунок 4.39. Диалог обратного вызова 'конфликты при слиянии'

Диалог обратного вызова 'конфликты при слиянии'


При возникновении конфликта во время слияния, у вас есть три возможности для его обработки:

  1. You may decide that your local changes are much more important, so you want to discard the version from the repository and keep your local version. Or you might discard your local changes in favour of the repository version. This only relates to conflicting changes. Changes that can be merged are still merged. Only for the conflicting part your choice is used.

  2. Обычно вы желаете посмотреть на конфликты и уладить их. В этом случае, выберите Редактировать конфликт, которая запустит ваш инструмент слияния. Когда вы будете удовлетворены результатом, нажмите на Улажено.

  3. Последняя возможность - отложить разрешение конфликта и продолжить слияние. Вы можете сделать это как с текущим конфликтующим файлом, так и со всеми оставшимися для слияния файлами. Однако, если в этом файле есть дальнейшие изменения, завершить слияние будет невозможно.

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

Слияние завершённого ответвления

Если вы желаете произвести слияние всех изменений из ответвления новой функции со стволом, то вы можете использовать пункт TortoiseSVNВоссоединительное слияние... из расширенного контекстного меню (нажмите и удерживайте клавишу Shift при правом щелчке на файле).

Рисунок 4.40. Диалог 'Воссоединительное слияние'

Диалог 'Воссоединительное слияние'


Использовать этот диалог очень просто. Всё, что вы должны сделать - это задать параметры для слияния, как описано в «Параметры слияния». Остальное TortoiseSVN сделает самостоятельно, используя информацию об отслеживании слияний.

Сопровождение ответвления разработки новой возможности

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

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

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