Выбор стратегии ветвления и слияния в Team Foundation Server (TFS)
ОГЛАВЛЕНИЕ
Как использовать данную статью
Данная статья рассказывает, когда следует и когда не следует прибегать к ветвлению. Если принято решение о необходимости ветвления в конкретной ситуации, то эта глава научит использовать ветвление и слияние эффективно.
В данной статье предлагается обзор ветвления и слияния: в ней приведены различные стратегии ветвления и показаны сценарии, когда применение ветвления уместно. Если вас интересует конкретный сценарий, переходите прямо к соответствующему разделу. Чтобы извлечь максимальную пользу из этой статьи, следует:
- Использовать список сценариев. В списке сценариев выберите тот, который ближе всего подходит к вашей ситуации. Следуя рекомендациям, создайте разветвленную структуру каталогов, отвечающую вашим нуждам.
- Использовать сопроводительное руководство. Руководствуйтесь рекомендациями по ветвлению и слиянию, приведенными в разделе «Рекомендации по работе с системой контроля версий» данного руководства.
Сценарии ветвления и слияния
Далее приведены сценарии, в которых может понадобиться создавать ветви и выполнять слияния:- Ветвь разработки должна быть создана при наличии постоянных проблем с дефектными сборками для изолирования параллельных процессов разработки.
- При наличии функциональности, обусловливающей нестабильное поведение, или если одновременная работа групп приводит к возникновению нестабильности в разрабатываемой системе, в папке-контейнере системы контроля версий следует создать отдельные ветви функциональных возможностей или групп разработки.
Не следует использовать ветвление, если в нем нет крайней необходимости. Ветвление требует дополнительного обслуживания каталога исходного кода и выполнения задач по слиянию. Для большинства групп разработки, которые занимаются созданием бизнес-приложений и имеют короткие циклы выпуска новых версий, ветвления не требуется. Группам разработки, реализующим более длинные циклы выпуска, таким как Независимые производители ПО (Independent Software Vendors, ISV), которые создают «коробочные» приложения, скорее всего, придется прибегнуть к ветвлению в своем процессе разработки.
Если разработка ведется последовательно, и каждая последующая версия является лишь доработанным и расширенным вариантом предыдущей, то ветвление может потребоваться только в случае частых несовместимых между собой изменений, дестабилизирующих процесс разработки.
Типовые сценарии на практике
Рассмотрим типовые сценарии ветвления:
- Сценарий 1 – Нет ветвления. Группа работает только с основным деревом исходного кода. В данном случае ветви не создаются, и в изоляции нет необходимости. Такой сценарий обычно подходит для небольших или средних групп, где не требуется изоляция по группам или по функциональным возможностям и не нужно изолировать версии, готовые к выпуску.
- Сценарий 2 – Ветвление для выпуска версии. Группа создает ветви для поддержки выпускаемой версии. Это второй наиболее распространенный случай, когда ветвление используется для стабилизации выпускаемой версии. В данном случае группа создает ветвь перед выпуском версии, чтобы стабилизировать ее, и затем, после выпуска версии ПО, вносит изменения из ветви выпущенной версии в основную ветвь исходного кода.
- Сценарий 3 – Ветвление для обслуживания. Группа создает ветвь для сохранения старой сборки. В данном случае ветвь создается с целью обслуживания, чтобы не дестабилизировать сборки, находящиеся в производственной эксплуатации в настоящее время. Изменения этой ветви могут, как переноситься, так и не переноситься в основное дерево. Например, для некоторой группы пользователей может создаваться решение для быстрого исправления дефекта, которое не требуется включать в основную сборку.
- Сценарий 4 – Ветвление для разработки функциональной возможности. Группа создает ветви на основании имеющихся функциональных возможностей. В данном случае создается ветвь разработки, все работы ведутся в ней и затем все выполненные изменения переносятся в основную ветвь исходного кода. Создание отдельных ветвей для функциональных возможностей позволяет работать над ними параллельно.
- Сценарий 5 – Ветвление для изоляции группы. Ветви создаются с целью изоляции подгрупп, чтобы обеспечить им возможность работы без конфликтов, порождаемых несовместимыми между собой изменениями в исходном коде, или чтобы они могли работать параллельно и выполнять синхронизацию по завершении собственных этапов, характерных для этой группы.
В своей работе разработчик может столкнуться с одним и более сценариев. Их следует использовать как эталон для определения возможности применения той или иной рекомендации в конкретном случае.
Примеры именования папок и их назначение
Ниже приведены примеры именования папок, которые могут быть созданы в системе контроля версий Microsoft® Visual Studio® Team Foundation Server (TFS) при структурировании дерева исходного кода в сценариях ветвления и слияния.
- Папка Development ответвляется от Main и используется для изолирования кода, находящегося в активной разработке. Ветви разработки могут быть временными и создаваться только на период работы над опасными изменениями, чтобы не оказывать влияния на содержимое папки Main.
- Папка Main содержит основной каталог исходного кода. Все изменения из остальных ветвей интегрируются здесь.
- Папка Releases содержит ветви с уже выпущенным кодом, который теперь требуется обслуживать. Она изолирует этот код от кода, размещающегося в ветви разработки и участвующего в активной разработке. Также в этой папке находится ветвь текущей версии, которая ответвляется от Main и содержит версию, неконтролируемые изменения в исходный код которой запрещены по причине подготовки к выпуску. В этой ветви идет подготовка ПО к выпуску, тогда как в ветви Development продолжается работа над новой функциональностью.
В следующих разделах рассматривается использование ветвления в каждом из описанных выше сценариев, и приводятся конкретные примеры.
Сценарий 1 – Нет ветвления
Данный сценарий обычно применяется в небольших группах, для которых не стоит вопрос о необходимости изолированной разработки. Используя маркировку сборок метками, можно извлекать соответствующий исходный код. Во введении сложного ветвления нет необходимости, потому что работать можно непосредственно из папки Main. Вот представление сценария без ветвления:
My Team Project
Main
Source
Сценарий 2 – Ветвление для выпуска версии
В этом сценарии группа создает ветвь для стабилизации версии и, после выпуска версии ПО, объединяет ветвь этой версии с основным деревом исходного кода:
My Team Project
Main -> Главная ветвь интеграции
Source
Releases
Release 1 -> Ветвь выпускаемой версии
Source
Сценарий 3 – Ветвление для обслуживания
В данном сценарии создается ветвь для решения задач обслуживания, чтобы не вносить нестабильность в сборки, находящиеся в производстве. Ниже приведено представление ветвей обслуживания. Это представление очень похоже на ветвь для выпуска версии, однако в данном случае ветвь сохраняется в течение длительного времени для обеспечения поддержки версии:
My Team Project
Main -> Главная ветвь интеграции
Source
Releases -> Контейнер ветви обслуживания
Release 1 -> Ветвь обслуживания
Source
Other Asset Folders
Release 2 -> Ветвь обслуживания
Source
Other Asset Folders
Сценарий 4 – Ветвление для разработки функциональной возможности
В данном сценарии создается ветвь разработки, выполняется некоторая работа в этой ветви, и затем она объединяется с основным деревом исходного кода. Организовываются ветви разработки, исходя из функциональных возможностей продукта. Ниже приведено физическое представление ветвления для разработки функциональной возможности:
My Team Project
Development -> Контейнер ветви изолированной разработки
Feature A -> Ветвь функциональной возможности
Source
Feature B -> Ветвь функциональной возможности
Source
Feature C -> Ветвь функциональной возможности
Source
Main -> Главная ветвь интеграции
Source
Сценарий 5 – Ветвление для изоляции группы
Данный сценарий аналогичен предыдущему с ветвлением по функциональности, за исключением того, что ветви организовываются по подгруппам разработчиков, а не по функциональным возможностям. Возможно соответствие один-к-одному между группой и функциональной возможностью, но в некоторых случаях одна группа может
заниматься несколькими функциями. Ниже показано физическое представление ветвления по подгруппам:
My Team Project
Development -> Контейнер ветви изолированной разработки
Team 1 -> Ветвь группы
Feature A -> Изолированная ветвь для разработки
Source
Feature B -> Изолированная ветвь для разработки
Source
Team 2 -> Ветвь группы
Feature A -> Изолированная ветвь для разработки
Source
Feature B -> Изолированная ветвь для разработки
Source
Main -> Главная ветвь интеграции
Source
Логическая структура
Логическая структура представляет отношение родитель/потомок для каждой ветви. Она может отличаться от физической структуры, отображаемой в Source Control Explorer. Например, в представленной выше физической структуре кажется, что Development и Main равнозначны, тогда как на самом деле Development является дочерней папкой Main. На рис. 5.1 показан пример логической структуры и потока ветвлений и слияний в ней.

Сценарий выпуска версии продукта
На рис. 5.2 показана типовая временная диаграмма ветвления для выпуска версии продукта:
Рис. 5.2 Временная диаграмма ветвления для выпуска версии
Последовательность событий:
- Ветвь Release 1 создается из Main, как только реализована вся предполагаемая для данной версии функциональность.
- Ветвь Release 1 периодически сливается с Main, что гарантирует перенос исправлений дефектов из выпускаемой версии в основную интегрирующую ветвь.
- Сборка выпускаемой версии маркируется меткой в ветви версии для тиражирования (RTM), изменения вносятся в Main.
- Выходит пакет обновлений, SP1. Сборка маркируется, и изменения вносятся в Main.
- Ветвь Release 1 продолжает существование для поддержки SP1 и для обеспечения возможности создания новых пакетов обновлений.
Этот процесс повторяется для будущих версий продукта.
Примечание: При внесении исправлений в ветви версий важно определиться, в какую ветвь должно быть внесено это исправление, прежде чем реализовывать его. Если исправление выпускается как исправление в уже выпущенной версии (hotfix) или пакет обновлений, то сначала вносятся изменения в соответствующую ветвь Release (Выпускаемая версия), а затем эти изменения вносятся в Main, чтобы гарантировать их присутствие в будущих версиях.
Сценарий изолированной разработки
На рис. 5.3 показана типовая временная диаграмма ветвления для изолирования разработки.

Рис. 5.3 Временная диаграмма ветвления для изолирования разработки
Последовательность событий:
- Создается ветвь для изолированной разработки Функциональной возможности А.
- Создается ветвь для изолированной разработки Функциональной возможности B.
- Каждая группа по завершении определенного этапа работ переносит свои изменения в Main, что обеспечивает возможность их интегрирования в основную сборку и использования другими группами.
- С заданной периодичностью каждая группа переносит последние изменения из Main с целью синхронизации с работой остальных групп и для сокращения количества конфликтов при последующих слияниях.
- По завершении работы над функциональной возможностью все изменения переносятся в Main, и ветвь функциональной возможности уничтожается.
Вопросы ветвления
При ветвлении необходимо руководствоваться следующими рекомендациями:
- Прибегать к ветвлению следует только в случае, если группа разработки должна работать с одним набором файлов параллельно с другой группой. В
- противном случае, сборку можно маркировать меткой и создать ветвь от нее позднее. Слияние ветвей может быть сложным и требовать много времени, особенно если внесены существенные изменения.
- Ветви должны быть структурированы таким образом, чтобы слияние приходилось производить лишь вдоль по иерархии (вверх или вниз по ветви), а не поперек иерархии. Ветвление поперек иерархии требует использования слияния без общей родительской версии, при котором большинство конфликтов приходится разрешать вручную.
- В основе иерархии ветвей лежат ветвь-родитель и ветвь-потомок, и эта иерархия может отличаться от физической структуры исходного кода на диске. При планировании слияний необходимо руководствоваться логической структурой ветвления, а не физической структурой каталога исходного кода на диске.
- Не следует создавать слишком разветвленные структуры, поскольку тогда на внесение изменений в основную ветвь исходного кода и на разрешение конфликтов уходит слишком много времени. Сильно разветвленная структура может означать, что распространение изменений, выполненных в дочерней ветви, на основную ветвь исходного кода может занять очень большой период времени. Это, как правило, имеет негативное влияние на сроки выполнения проекта и увеличивает время, необходимое для исправления дефектов.
- Ветвление следует выполнять на высоком уровне и включать конфигурационные и исходные файлы.
- Развивать структуру ветвления следует постепенно.
- Для выполнения слияния и разрешения конфликтов требуется один или более разработчиков. После слияния исходный код должен быть тщательно протестирован, потому что очень часто неверные решения при слиянии приводят к дестабилизации сборки.
- Слияние поперек иерархии ветвей представляет особую сложность. При таком слиянии многие конфликты, которые могли бы обрабатываться автоматически, приходится обрабатывать вручную.
Вопрос о том, следует ли создавать ветвь, можно свести к вопросу, будут ли затраты на решение конфликтов в режиме реального времени выше, чем общие затраты на разрешение конфликтов при слиянии ветвей.
Рекомендации по работе над большим проектом
Большим группам разработки с длительными циклами разработки присущи следующие черты:
- Им нужна более сложная структура ветвления и слияния.
- Для них более высока вероятность работы с зависимостями между решениями и групповыми проектами.
- Для них более высока вероятность работы с несколькими сценариями сборки для компонентов и групп.
Вероятнее всего, большие группы будут использовать ветвление, как по группам, так и по функциональным возможностям, а также одна или более ветвей будут использоваться для интеграции внешних зависимостей. Поскольку структура ветвления глубже, то и промежуток времени между изменением в коде ветви разработки и внесением этого изменения в главную ветвь интеграции тоже больше. По этой причине при создании ветвей необходимо более тщательно продумывать стратегию слияния.
Например, при определении схемы слияния (будет ли она выполняться по графику или управляться событиями) необходимо учесть следующее
- Обратная интеграция обычно выполняется по графику, например, перенос изменений из ветви разработки в главную ветвь.
- Прямая интеграция, например, перенос изменений из главной ветви интеграции в ветвь разработки, обычно выполняется по некоторому событию, например, по завершению определенного этапа разработки. Это событие имеет место, когда группа, ответственная за ветвь разработки, чувствует, что готова перенести изменения из родительской ветви.
Необходимо найти компромисс между стратегией ветвления/слияния и предполагаемой частотой выполнения сборок. Более глубокая структура ветвления означает большее время интегрирования кода дочерних ветвей в главную ветвь исходного кода. Признаками неверного выбора стратегии ветвления являются:
- Дефектные сборки, потому что перенос исправлений дефектов в главную ветвь требует слишком много времени.
- Невыполнение сроков разработки, потому что требуется слишком много времени на распространение внесенных изменений в главную ветвь.
- На перенос изменений из ветви в ветвь требуется очень много времени.
Если это становится проблемой для группы, необходимо рассмотреть возможность уменьшения глубины структуры ветвления. Вот пример сложной структуры ветвления:
- My Team Project
- Development – Контейнер для изолирования активных ветвей разработки
- Feature A – Изолированная ветвь разработки
- Source
- Feature B – Изолированная ветвь разработки
- Source
- Main – Главная ветвь интеграции и сборки. Все изменения сводятся воедино здесь.
- Source
- Other Asset Folders
- Releases – Контейнер для ветвей текущей версии и обслуживания
- Release 2– Активная ветвь обслуживания
- Source
- Other Asset Folders
- Release 3 – Активная ветвь обслуживания
- Source
- Other Asset Folders
- Release 4 – Ветвь, содержащая код, находящийся на этапе подготовки к выпуску, внесение неконтролируемых изменений в который запрещено
- Source
- Other Asset Folders
- Safe Keeping
- Release 1 – Ветвь архивного хранения старой версии
- Source
- Other Asset Folders
Данная структура включает:
- Ветви функциональных возможностей для обеспечения изолированной работы нескольких групп.
- Главную ветвь, в которой собираются все изменения от всех групп, а также исправления дефектов из ветвей версий, готовых к выпуску.
- Ветвь версии, готовой к выпуску, используемая для фиксации и предотвращения неконтролируемого изменения текущей версии продукта.
- Ветвь обслуживания старой версии, которая активно обслуживается и поддерживается.
- Ветви архивного хранения старых версий, которые больше не обслуживаются.
Заключение
Ветви обычно создаются, для того чтобы предотвратить изменение выпускаемой версии, для обслуживания предыдущей версии продукта или для поддержки изолированной параллельной разработки. Не следует прибегать к ветвлению без веских на то оснований.
При создании ветвей необходимо логически структурировать их таким образом, чтобы затем производить слияние лишь вдоль иерархии (вверх и вниз по ветви), а не поперек иерархии. Слияние поперек иерархии требует достаточно много времени и может приводить к множеству ошибок.
Для больших групп структура ветвления глубже, поэтому необходимо быть готовыми к тому, что между внесением изменений в ветвь разработки и распространением их на главную ветвь интеграции проходит довольно много времени.