Выбор правильной стратегии ветвления для релизов

11

Начиная с новой команды разработчиков в новом проекте, и мы должны определить нашу стратегию ветвления для нашего исходного репозитория ( например, Microsoft Team Foundation Server 2010 ). Мы столкнулись с липкой дискуссией о том, стоит ли ...

. Иметь одну ветку Release, из которой мы производим производственные сборки, а затем Label, когда что-то действительно выпущено.

ИЛИ ЖЕ

B . Иметь новую ветку Release для каждой новой версии в производство ( например, Version 1, 2, 3 и т. Д. )

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

У кого-нибудь есть опыт, который мог бы помочь нам решить? В частности, я хочу услышать, где болевые точки для любого выбора. Не стесняйтесь предоставлять конкретный опыт относительно последствий TFS и / или Release-Management.

JoeGeeky
источник

Ответы:

15

Вариант А. Просто использование основной линии и тегов для выпуска

Плюсы:

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

Минусы:

  • Работа с незавершенными работами становится проблемой и увеличивает потенциальную поверхность атаки, когда наступает время ее выпуска. Однако, если ваши разработчики дисциплинированы, новые функции должны быть настраиваемыми и модульными и, следовательно, легко отключаться / включаться, или WIP отсутствует, и в каждой точке выпуска вся работа либо завершена, либо еще не была начата (например, Scrum).
  • Крупномасштабные / внеполосные изменения требуют более обдуманного заблаговременного внедрения (например, ветвление по абстракции).

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

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

Вариант Б. Ветвление по выпуску

Плюсы:

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

Минусы:

  • Тонны веток.
  • Еще нужно пометить ветки в точках выпуска.
  • Еще нужно разобраться с WIP и объединить WIP из предыдущей ветки релиза в следующую ветку релиза, если он не собирается это делать, и все равно нужно отключить или восстановить его из ветки релиза и повторно запустить приемочные тесты
  • Горячие исправления должны быть применены к большему количеству веток (ветвь релиза + исправление + новый тег + исправление слияния с веткой vnext и, возможно, vnextnext в зависимости от того, куда упало исправление.)

Я не большой поклонник этого решения ^ _ ^.

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

В идеале, хотя я думаю, что вы хотите, чтобы это был процесс исключения, а не правило.

Вариант C. Безумный Бонус Вариант

Если вы хотите получить фантазию, вы также можете рассмотреть модель ветвления для каждой пользовательской истории / функции. ( Ужасная идея в TFS или любой другой, не DVCS, и в то же время невероятно тривиальная реализация при использовании DVCS, как git или mercurial ).

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

  1. Особенности были разработаны разработчиками в их командах разработчиков.
  2. Когда функция готова к рассмотрению коллегами, разработчики объединяют ее в одно объединение из ветви Dev в ветку CR и включают в заголовок идентификатор функции / историю пользователя. * Усиливается с помощью pre-commit hook *
  3. После прохождения CR используется инструмент администратора для продвижения функции в ветку QA. (Я написал небольшое терминальное приложение, в котором перечислены пользовательские истории, присутствующие на различных этапах приемки, и позволил оператору продвигать или понижать его между этими этапами приемки).
  4. QA проводит тесты автоматизации и ручного юзабилити. Если функция хороша, ее помещают в ветку релиза (mainline). Если функция отклонена, ее понижают / возвращают из ветви QA, пока разработчики не смогут решить проблемы, поднятые во время тестирования, и добавить отправку патча в ветку CR.
  5. Если код был возвращен из ветви QA и применено исправление, инструмент терминала повторно применяет необходимые изменения, чтобы перенести функцию обратно в ветку QA из ветви CR, чтобы QA мог пересмотреть код и либо продвинуть его, либо понизить это снова.
  6. В любой момент времени ветвь релиза должна находиться в стабильном состоянии.
  7. После выпуска новые Dev, QA и CR выводятся из основной линии.
Кит Брингс
источник
@Keith_Brings Это действительно хорошее резюме, спасибо. Как вы уже указали, вариант C на самом деле не является вариантом, поскольку я использую TFS, но тем не менее интересен.
JoeGeeky
Я не понимаю, как вариант А может работать. В моей компании у нас разные версии для разных клиентов. Если мы все еще занимаемся разработкой функций / исправлений для версии 1.0, а также активно работаем над версией 2.0, а может быть, даже 3.0, мы не сможем сделать все это в одной ветке. Возможно, у вас есть возможность насладиться вариантом А из-за вашей модели выпуска. Но это не релиз модели каждого, и для тех из нас застрял с функцией ползучести или нескольких выпусков параллельно, мы должны использовать Вариант B.
void.pointer
6

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

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

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

Не беспокойтесь о количестве веток или о времени, которое они проводят без изменений. Ваша система управления версиями должна предоставить вам контроль и предоставить историю развития вашего проекта. История имеет тенденцию не меняться ... И не беспокойтесь, что ваши cvs не справятся. Мы используем Perforce, более 9000 файлов в ветви разработки, до 50 веток разработки для выпусков, над которыми мы работаем, и, как уже было сказано, по одной ветке на выпуск, который мы публикуем. Perforce даже не дышит тяжелее.

Короче говоря: упростите свою жизнь в качестве разработчика / сопровождающего / исправителя ошибок / охотника за проблемами и не беспокойтесь о количестве веток или количестве файлов. Любой уважающий себя cvs справится.

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

Мы не испытываем никакой путаницы в отношении количества филиалов, которые у нас есть. Наша схема именования веток релиза и наша политика веток 1 выпуск 1 для ветвей разработки (или работы) могут иметь к этому отношение.

Ветви выпусков названы для выпуска, который они содержат, то есть: R2011SP1 для Выпуска 2011 с пакетом обновления 1. Наши рабочие ветви имеют менее интеллектуальные имена: sub01, sub02, sub03 и т. Д. «Sub» происходит от того факта, что все рабочие ветви являются подветвлениями. приемной ветви. Приемная ветвь, в которой собраны все вопросы, готовые к выпуску.

Наша политика работы 1 выпуска 1 в сочетании с тем фактом, что наша система отслеживания ошибок была настроена с полем «филиал», гарантирует, что мы всегда знаем, какая проблема разрабатывается в каком филиале. Когда проблема интегрирована в ветку принятия, это поле обновляется. Это означает, что мы всегда знаем, какие проблемы готовы к выпуску (как только будет выполнено приемочное тестирование). Точно так же мы обновляем это поле при создании ветки релиза, и таким образом мы всегда можем отследить, в каком выпуске выпущена проблема.

Марьян Венема
источник
1
Я считаю, что вы можете переходить от меток в TFS. Так что вы должны быть готовы к исправлениям в текущих версиях продукта, если вы не забыли ярлык.
Кит Брингс
@KeithBrings Это правильно, я только что проверил это, и вы действительно можете перейти с метки.
JoeGeeky
@MarjanVenema Я не столько обеспокоен загрузкой системы, сколько путаницей, которую может вызвать большое количество веток. Я также немного обеспокоен тем, что изменения, внесенные в стек ветвей релизов, не будут объединены с другими ветвями релизов, которые должны их получать, не говоря уже о основной линии. Вы сталкивались с такими проблемами?
JoeGeeky
@JoeGeeky: нет, нет путаницы вообще. Смотрите обновление к моему ответу.
Марьян Венема
2

Все дело в контексте: как часто вы выпускаете и что в релизе.

Вот небольшой пример из моей старой работы с использованием метода B (мы называли его ветвью по назначению ).

Чтобы поместить историю в контекст,

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

Основная разработка была сделана в стволе, пока мы не достигли состояния полной функциональности для определенного выпуска. В этот момент мы создадим ветку с именем projectname-january2012 и проведем тестирование качества и исправление ошибок в этой самой ветке. Как только мы были готовы к публичному выпуску, мы помечали код в этой ветке и выпускали.

Однако разработка релиза на этом тэге не закончилась. Неизбежно, у нас были клиенты, которые обнаружили ошибки или небольшие проблемы с релизом. Таким образом, в этом случае все, что нам нужно сделать, - это вернуться в эту ветку, исправить код и создать новую версию тега ветки january2012, которая будет выпущена, и объединить исправления со стволом.

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

Итак, вопросы, которые вы должны задать себе:

  • Как часто я выпускаю?
  • Мои релизы будут на 100% обратно совместимы?
  • Удастся ли моим клиентам полностью обновить систему, чтобы исправить ошибки?

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

Bushibytes
источник
Мне нравится, как вы называете этот вариант. В этом случае мы являемся нашими собственными клиентами ( если можно так выразиться ), поэтому развертывание в значительной степени останется под нашим контролем. Мы также являемся магазином Scrum и ожидаем, что у нас будут довольно частые циклы выпуска ( например, каждые 2-4 недели ). Хотя мы надеемся поддерживать непрерывные обновления, обратная совместимость будет проблемой только в течение времени, необходимого для развертывания обновлений, так что ... возможно, минут. От этого звука этого; в вашем опыте; вариант Б может быть не лучшим выбором для меня. Спасибо за информацию, очень интересно.
JoeGeeky
Ах да, в этом случае вариант B звучит как беспорядок с небольшим возвратом. Я просто хотел подчеркнуть, что оба варианта жизнеспособны и имеют у каждого свои преимущества. Я забыл прямо упомянуть: как вы справляетесь с исправлениями ошибок? Они помещены исключительно в новые выпуски или в исправлениях / исправленных старых выпусках?
Bushibytes
1

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

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

Несколько вещей для рассмотрения.

  • Перенесите исправления вперед через все ветви активного кода. Это может быть сделано путем слияния, исправления и / или повторной разработки. Они должны полностью управляться, чтобы гарантировать, что исправление применяется ко всем соответствующим выпускам, а затем к транку.
  • Рассмотрим ветви функций, чтобы позволить разработку функций в изоляции от основного потока кода. Они рекомендуются для экспериментальных изменений. Не стесняйтесь оставлять ветви функций, если функция не работает.
  • Отметьте и отследите ваши точки слияния.
  • Разветвите свои релизы при необходимости Я нахожу, что это нормально, когда релиз готов к выпуску сборок-кандидатов. В некоторых случаях внесение несовместимых изменений в ствол может вызвать и раннее ветвление. Рассмотрим функцию ветки.
BillThor
источник
0

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

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

Поэтому я рекомендую что-то, что действительно является смесью как А, так и В ; оба имеют хорошие аспекты, но ни одно не является полным само по себе. Используйте лучшее из обоих миров.

Donal Fellows
источник
0

Я использовал TFS для эффективной реализации опции (B) в прошлом.

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

Потому что ветвление является спорным, если система не создает автоматически и не запускает тесты для вашей ветки.

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

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

Крейг Брунетти
источник