Слияние

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

Вы должны указать опорную (peg) ревизию для слияния, добавить опорную ревизию в конец ревизий, например, 5-7,[email protected]. В вышеприведенном примере ревизии 5,6,7 и 10 будут слиты, при этом ревизия 3 опорная.

Важно

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

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

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

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

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

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

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

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

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

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

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

Если вы оставили диапазон ревизий пустым или выбрали переключатель все ревизии, то Subversion сливает все необъединённые ревизии. Это известно как воссоединительное или автоматическое слияние.

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

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

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

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

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


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

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

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

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

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

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

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

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

Почти всё время вы хотите сливать с учетом истории файлов, так чтобы изменения по сравнению с общим предком объединяются. Иногда вам может понадобиться слить файлы, которые возможно связаны, но не в вашем хранилище. Например, у вас могут быть импортированы версии 1 и 2 сторонней библиотеки в две разные директории. Несмотря на это, логически они связаны, но Subversion об это не знает, т. к. ему видны только импортированные архивы. Если вы попытаетесь слить различия между этими двумя деревьми, то можете увидеть полное удаление и следующее за ним полное добавление. Чтобы заставить Subverison использовать различия по путям, а не по истории, отметьте флажок Игнорировать предков. Почитайте на эту тему книгу по Subversion Noticing or Ignoring Ancestry.

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

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

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

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

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

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

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

Подсказка

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

Для настройки этого созданного сообщения установите соответствующие свойства проекта в вашей рабочей копии. Смотрите «Шаблоны сообщения журнала для слияния»

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

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

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

Подсказка

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

Важно

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

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

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

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

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

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

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

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

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

Больше информации об отслеживании слияния найдете в документации Subversion Merge tracking documentation.

Обработка конфликтов после слияния

Важно

The text in the conflict resolver dialogs are provided by the SVN library and might therefore not (yet) be translated as the TortoiseSVN dialogs are. Sorry for that.

Merging does not always go smoothly. Sometimes there is a conflict. TortoiseSVN helps you through this process by showing the merge conflict dialog.

Рисунок 4.57. Диалог конфликта слияния

Диалог конфликта слияния


It is likely that some of the changes will have merged smoothly, while other local changes conflict with changes already committed to the repository. All changes which can be merged are merged. The Merge Conflict dialog gives you different ways of handling the lines which are in conflict.

For normal conflicts that happen due to changes in the file content or its properties, the dialog shows buttons which allow you to chose which of the conflicting parts to keep or reject.

Postpone

Don't deal with the conflict now. Let the merge continue and resolve the conflicts after the merge is done.

Accept base

This leaves the file as it was, without neither the changes coming from the merge nor the changes you've made in your working copy.

Accept incoming

This discards all your local changes and uses the file as it arrives from the merge source.

Reject incoming

This discards all the changes from the merge source and leaves the file with your local edits.

Accept incoming for conflicts

This discards your local changes where they conflict with the changes from the merge source. But it leaves all your local changes which don't conflict.

Reject conflicts

This discards changes from the merge source which conflict with your local changes. But it keeps all changes that don't conflict with your local changes.

Пометить как улаженный

Marks the conflicts as resolved. This button is disabled until you use the button Edit to edit the conflict manually and save those changes back to the file. Once the changes are saved, the button becomes enabled.

Редактировать

Starts the merge editor so you can resolve the conflicts manually. Don't forget to save the file so the button Mark as resolved becomes enabled.

If there's a tree conflict, please first see «Конфликты деревьев» about the various types of tree conflicts and how and why they can happen.

To resolve tree conflicts after a merge, a dialog is shown with various options on how to resolve the conflict:

Рисунок 4.58. The Merge Tree Conflict Dialog

The Merge Tree Conflict Dialog


Since there are various possible tree conflict situations, the dialog will show buttons to resolve those depending on the specific conflict. The button texts and labels explain what the option to resolve the conflict does. If you're not sure, either cancel the dialog or use the Postpone button to resolve the conflict later.

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

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

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

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

Другой (быстрый) способ слить все изменения из ствола (trunk) в ветку новой функции это использовать TortoiseSVNСлить всё... из расширенного контекстного меню (удерживайте клавишу Shift при правом клике на файле).

Рисунок 4.59. Диалог 'Слить Всё'

Диалог 'Слить Всё'


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