Лучшая стратегия ветвления при непрерывной интеграции?

100

Какую стратегию ветвления лучше всего использовать, если вы хотите осуществить непрерывную интеграцию?

  1. Разветвление выпуска: развивайте в стволе, сохраняйте ветку для каждого выпуска.
  2. Ветвление функций: разрабатывайте каждую функцию в отдельной ветке, объединяйте только после стабильной работы.

Имеет ли смысл использовать обе эти стратегии вместе? Например, вы переходите для каждого выпуска, но вы также переходите для крупных функций? Лучше ли сочетается одна из этих стратегий с непрерывной интеграцией? Будет ли иметь смысл использование непрерывной интеграции при использовании нестабильной магистрали?

КорольНестор
источник
2
Боковое примечание: некоторые утверждают, что даже когда в него добавляются новые функции, все всегда должно быть стабильным. С другой стороны, это может быть несколько идеалистическим.
Кейт Пинсон

Ответы:

21

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

  • Я помню, как Марк Шаттлворт предложил модель сохранения основной ветви в первозданном виде, выходя за рамки обычного CI. Я написал об этом здесь .
  • Так как я знаком с круиз - контролем, я также писал о филиалах группы и CI здесь . Это пошаговое руководство, объясняющее, как это сделать с помощью Plastic SCM .
  • Наконец, я обнаружил, что некоторые темы о CI (и, возможно, разговоры о ветвлении) в книге Дюваля по CI тоже очень интересны. .

Надеюсь, ссылки будут вам интересны.

пабло
источник
Мы добавили поддержку Bamboo для создания веток для каждой задачи codicesoftware.blogspot.com/2012/02/… , и, похоже, их новейшая версия будет делать это изначально с несколькими элементами управления версиями, включая dvcs.
Пабло 05
20

Ответ зависит от размера вашей команды и качества вашей системы управления версиями, а также от способности правильно объединять сложные наборы изменений. Например, при полном управлении исходным кодом ветви, таком как слияние CVS или SVN, может быть сложно, и вам может быть лучше с первой моделью, в то время как при использовании более сложной системы, такой как IBM ClearCase, и с большим размером команды вам может быть лучше со второй. модель или их комбинация.

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

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

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

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

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

Иржи Клоуда
источник
5
Я не уверен, согласен ли я с тем, что то, что вы описываете, не имеет смысла для команд до 50 разработчиков. Я также вижу выгоду для гораздо меньших команд. +1
Aardvark
2
Конечно, есть преимущества для команд любого размера. Вопрос в том, при каком размере команды преимущества перевешивают затраты, связанные с тяжелым процессом.
Иржи Клоуда
Это похоже на модель GitFlow и / или GitHubFlow. Я не думаю, что эти модели способствуют непрерывной интеграции (CI). На мой взгляд, Trunk Based Development - значительное улучшение этих моделей.
Yani
Вы можете видеть, что этот комментарий на самом деле предшествует первоначальному выпуску git flow. Не совсем понимаю, что вы имеете в виду под словом «лучше». Я поддерживал команды из 1, 5, 25, 150, 1000 и 20 000 разработчиков, работающих над проектами, которые были в той или иной степени интегрированы. Требования меняются, и термин «лучше» очень относительный. Вам когда-нибудь нужно было переносить код? Исправления безопасности? Если нет, то ваша жизнь проста. SaaS является прямым результатом ограничений, налагаемых разработкой на основе магистрали. Флаги функций так же сложны, как и ветви функций. За исключением того, что вы узнаете об этом только от клиентов, когда их перестановка сломается.
Иржи Клоуда
9

Лично я считаю, что иметь стабильный ствол и разветвлять функции намного удобнее. Таким образом, тестировщики и им подобные остаются на одной «версии» и обновляются из магистрали, чтобы протестировать любую функцию, код которой завершен.

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

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

Аднан
источник
Кроме того, вы все еще разветвляете и помечаете каждый основной выпуск? Или просто отметьте?
KingNestor
1
Он хорошо работает с CI до тех пор, пока функциональные ветки объединяются в ствол с некоторой дисциплиной, чтобы не иметь сломанных сборок. Я делаю ветвление и теги для каждого производственного выпуска, который будет использоваться только для исправления ошибок. Это может быть немедленно объединено в стабильный ствол.
Аднан
@king Я бы сказал, что это, вероятно, зависит от того, что вы называете основным выпуском, но в любом случае вы можете пометить и ветвиться позже, когда вам это нужно (на основе тега :))
eglasius
5

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

http://martinfowler.com/articles/continuousIntegration.html#EveryoneCommitToTheMainlineEveryDay

РЕДАКТИРОВАТЬ

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

Я попытаюсь объяснить, почему я так думаю. Предположим, что каждый из трех разработчиков берет ветку для работы над функцией. Для завершения каждой функции потребуется несколько дней или недель. Чтобы обеспечить непрерывную интеграцию команды, они должны выполнять фиксацию в основной ветке не реже одного раза в день. Как только они начинают это делать, они теряют возможность создания ветки функций. Их изменения больше не отделены от всех изменений других разработчиков. В таком случае зачем вообще создавать ветки функций?

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

ДРУГОЙ РЕДАКТИРОВАНИЕ

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

http://jamesmckay.net/2011/07/why-does-martin-fowler-not-understand-feature-branches/

Фил Хейл
источник
интересно, больше не могу найти этот пост.
Jirong Hu
5

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

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

Так что для меня использование обоих механизмов - очень хорошая стратегия.

Интересная ссылка из Книги СВН .

SirFabel
источник
4

Недавно мне понравилась эта модель при использовании git. Хотя ваш вопрос помечен как «svn», вы все равно можете его использовать.

Непрерывная интеграция может в некоторой степени происходить в ветке «разработка» (или как вы ее называете) в этой модели, хотя наличие длительных функциональных веток для будущих выпусков не сделает ее настолько жесткой, чтобы учитывать каждое изменение, происходящее где-то в коде. Остается вопрос, действительно ли вы этого хотите. Мартин Фаулер знает.

Германн
источник
2

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

Было сказано, что ...

  • нет причин, по которым CI нельзя использовать в обоих описанных вами подходах
  • эти подходы хорошо работают в сочетании
  • ни один из двух не работает «лучше», чем другой
  • CI имеет смысл при нестабильном стволе

На все это был дан ответ в четвертом вопросе на странице, с которой вы взяли диаграммы: http://blogs.collab.net/subversion/2007/11/branching-strat/

Зак Томпсон
источник
2

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

Чтобы лучше познакомиться с основной моделью, прочитайте это: https://web.archive.org/web/20120304070315/http://oreilly.com/catalog/practicalperforce/chapter/ch07.pdf

Прочтите ссылку. Когда вы освоите основы, прочтите следующую статью достопочтенного Хенрика Книберга. Это поможет вам связать основную модель с непрерывной интеграцией.

http://www.infoq.com/articles/agile-version-control

Зволков
источник
Глава О'Рейли больше недоступна
Джейсон С.
1

Когда мы начинали нашу команду, мы унаследовали стратегию на основе релизов от поставщика, который изначально разработал систему, за которую мы собирались отвечать. Это работало до тех пор, пока наши клиенты не потребовали, чтобы некоторые разработанные функции не были включены в релиз (например, ~ 250 тыс. Строк кода, ~ 2500 файлов, Scrum с XP SDLC).

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

Последний «гвоздь в крышку гроба» чистых SC-стратегий пришел, когда мы решили, что у нас должен быть 1. стабильный ствол и 2. рабочий должен содержать ST, UAT и регрессивно протестированные БИНАРИИ (а не только источник - подумайте CC).

Это привело нас к разработке стратегии, которая представляет собой гибрид между стратегиями SC на основе функций и релизов.

Итак, у нас есть багажник. В каждом спринте мы разветвляем ветвь спринта (для не гибких людей спринт - это просто ограниченная по времени разработка с переменным выходом в зависимости от сложности). Из ветки спринта мы создаем ветви функций, и в них начинается параллельная разработка. После того, как функции завершены, система протестирована и мы получаем намерение развернуть их, они объединяются в ветвь спринта - некоторые из них могут перемещаться по нескольким спринтам, обычно более сложные. Когда спринт подходит к концу и все функции завершены ... мы «переименовываем» ветвь спринта в «регрессию» (это позволяет CruiseControl выбрать ее без какой-либо реконфигурации), а затем начинается регрессионное / интеграционное тестирование на cc-built. EAR. Когда все это будет сделано, оно будет запущено в производство.

Короче говоря, функциональные ветви используются для разработки, тестирования системы и функциональности UAT. Ветвь спринта (на самом деле ветвь выпуска) используется для выборочного объединения функций по запросу и интеграционного тестирования.

Теперь вопрос к сообществу - у нас, очевидно, возникают проблемы с непрерывной интеграцией из-за того, что разработка происходит во многих ветвях, и накладных расходов на реконфигурацию CruiseControl. Может кто подскажет и посоветует?

XAvatar
источник
Я не обязательно согласен с выводами, но спасибо за обсуждение вашего процесса. Не существует универсального решения.
RaoulRubin
0

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

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

ps Где вы взяли эти ссылки на подходы? - не кажется, что эти графики представляют все варианты

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

eglasius
источник
Есть еще несколько. Но мне кажется, что ветвление функций и ветвление выпуска - два наиболее распространенных.
KingNestor
0

Дэйв Фарли , автор книги « Непрерывная доставка» , назвал разработку на основе магистрали (TBD) краеугольным камнем непрерывной интеграции (CI) и непрерывной доставки (CD). Он говорит:

Любая форма ветвления противоположна непрерывной интеграции.

Он также говорит:

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

Разработка на основе магистрали (TBD) - это практика интеграции изменений кода в магистраль (также известную как мастер, магистраль) не реже одного раза в день - предпочтительно несколько раз в день. Непрерывная интеграция (CI) представляет собой аналогичную практику, за исключением того, что она также включает проверку изменений кода с помощью автоматических тестов. Лучшая стратегия ветвления для этого - работать непосредственно из магистрали и выполнять проверки кода с помощью парного программирования . Если по какой-то причине вы не можете создать пару или просто хотите разветвиться, убедитесь, что ваши ветки недолговечны (менее суток).

Я работаю над Trunk, «мастером» в репозиториях GIT. Я обязуюсь выполнить локальное управление и сразу же, когда я подключен к сети, отправляю в центральное главное репозиторий, где работает CI. Это оно!

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

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

Яни
источник
Дэйв Фарли и Джез Хамбл просто ошибаются в своей позиции относительно ветвления. Причина этого в том, что он кодирует важное предположение «вам никогда не придется манипулировать кодом на уровне функций, и если, тогда это нормально, если это будет дорогостоящая операция», и они основывают свою оценку на другом предположении «слияние слишком дорого с автоматическим слияния почти невозможны в масштабе ". Если эти два предположения не верны, если вы живете в мире, где слияние обходится дешево, но вам нужно манипулировать кодом на уровне функций для обратных портов и исправлений безопасности, тогда их утверждения не работают. Хотя это редкий случай.
Иржи Клоуда
Некоторым компаниям также необходимо перенести функции в будущие выпуски после того, как эти функции столкнутся с препятствиями в реализации и задерживают выпуск. Иногда есть возможность оставить код, как в продуктах SaaS, но если код предоставляется клиентам, это может быть не вариант, поскольку его могут проанализировать конкуренты. В наши дни так много кода не компилируется, и даже если это так, флаги определений / функций в коде находятся на том же уровне сложности, что и ветви.
Иржи Клоуда
-3

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

  • Если вы используете Subversion, придерживайтесь варианта 1 и выпустите из веток.
  • Если вы используете GIT, вам подойдет вариант 2.
Тони Зампогна
источник
2
Разветвление