Слияние

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


В поле От: введите полный 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.54. Мастер слияния - слияние деревьев

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


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

В поле От: введите полный 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.

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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


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