0 23.2K ru

Branching стратегии в Git

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

Branching & merging анти-паттерны:

  • Merge Paranoia – когда девелоперы боятся мержить код, из-за последствий которые могут возникнуть (мерж конфликты) поэтому накапливается негативный эффект отложенной интеграции.
  • Merge Mania – когда разработчики больше времени тратят на объединение изменений, чем на разработку.
  • Big Bang Merge – В ветки не подмерживаются изменения, как следствие в конце происходит один гигантский мерж в конце.
  • Never-Ending Merge – непрерывный мержинг, так как всегда есть что мержить.
  • Wrong Way Merge – объединение более поздней бранчи с более ранней версией.
  • Branch Mania – создание большого количества веток без видимой на то причины.
  • Cascading Branches – создание веток без мержа их в mainline в конце разработки.
  • Mysterious Branches – создание ветки без причины.
  • Temporary Branches – создание ветки с изменяющейся причиной ее существования: ветка становится "permanent temporary workspac'ом".
  • Volatile Branches – старт ветки в нестабильном состоянии или перенос нестабильных изменений в другие ветки.
  • Development Freeze – остановка всей разработки для создания веток, объединения или создания релизов.
  • Berlin Wall – использование веток для разделения людей в команде, вместо разделения на таски/фичи, над которыми они работают.

Git Flow (Feature Based Development)

Схематично Git Flow можно описать так:

gitflow

Git Flow — одна из первых крупных стратегий ветвления, которая завоевала популярность. Git Flow описывает несколько веток для разработки, релизов и взаимодействия между ними.

Главные ветки:

main branches gitflowПо сути модель перекочевала с других существующих моделей. Репозиторий содержит 2 главные ветки:

  • master
  • develop

master — дефолтная ветка знакомая каждому, кто работал с гитом. Параллельно в этой концепции существует еще одна ветка develop.

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

В Git Flow мы можем использовать следующие типы веток:
  • Feature branches
  • Release branches
  • Hotfix branches

Feature branches

  1. Могут бранчеватся от develop
  2. Должны вмержится в develop
  3. Naming convention: любые названия кроме masterdeveloprelease-*, или hotfix-*

Release branches

  1. Могут бранчеватся от develop
  2. Должны вмержится в develop и master
  3. Naming convention: release-*

Помните, до того как вмержить код в релиз ветку, необходимо добавить ей тег с версией релиза (например "0.9 hotfix")

Hotfix branches

  1. Могут бранчеватся от master
  2. Должны вмержится в develop и master
  3. Naming convention: hotfix-*

Плюсы и минусы Git Flow:

Плюсы:

  1. Git Flow используется многими распределенными командами, в тч и open source команды, которые имеют разные уровни квалификации. Сопровождающие проекта могут проводить код ревью и утверждать каждую строку кода в релизы.
  2. Git Flow хорошо подходит для "традиционной модели релизов", где релизы делаются раз в месяц или раз в пару недель.
  3. Git Flow также хорошо работает при работе с установленным продуктом или несколькими версиями в производстве.


Минусы:

  1. Git Flow может замедлять работу, когда приходится ревьювить большие пулл реквесты, когда вы пытаетесь выполнить итерацию быстро.
  2. Релизы сложно делать чаще, чем раз в неделю.
  3. Большие функции могут потратить дни на мерж и резолв конфликтов и форсировать несколько циклов тестирования.
  4. История проекта в гите имеет кучу merge commits и затрудняет просмотр реальной работы.
  5. Может быть проблематичным в CI/CD сценариях.

GitHub Flow

github

Он выглядит почти так же как и Git Flow, но фиксированная ветка всего одна — master; всё остальное принадлежит тематическим ветвям. Тематические ветви, в свою очередь, создаются в форках — клонированных копиях репозитория. То есть центральный репозиторий тематических веток не содержит. В том числе и после слияния, так как метки веток при этом снимаются и их головы становятся анонимными.

GitLab Flow

Как и в GitHub Flow, фиксированная ветка всего одна — master, всё остальное принадлежит тематическим ветвям. Однако, если в том случае релизы размещались в коммитах master-a, то здесь для каждого релиза создаётся своя, отдельная ветка. Причём никакого мержа этих веток с parent'ом не производится. Если ветка отбранчевалась, значит она будет жить своей жизнью, получая исправления ошибок в виде отдельных коммитов (возможно, портированных из head/master с учётом накопившейся разницы в функционале между ветками).

Environment branches в GitLab flow

environment_branches

Release branches в GitLab flow

release branches

Trunk Based Development (TBD)

На официальном сайте эта концепция отображается такой схемой:

Trunk based development

Лично для меня, когда я стал изучать эту концепцию эта схема показалась совсем не понятной и не раскрывала суть этой концепции. Давайте же разберемся подробнее простым языком  в чем суть Trunk Based Development.

Что такое Trunk Based Development (TBD) ?

TBD прозволяет бизнесу тестировать бизнес-гипотезы "As soon as possible". Тк позволяет очень быстрыми итерациями релизить код на продакшн.

В Trunk Based Development можно выделить следующие особенности:

  1. Ветки живут максимум 2 дня
  2. Feature Flags
  3. Branch By Abstraction
  4. Continuous Code Review (это концепция из экстримального программирования которая говорит о том, что код который попадает на ревью, должен ревьювится как можно быстрее)
  5. master всегда готов к деплою, даже если в нем есть не готовые фичи

Feature Flags

Feature Flags — это концепция в которой у нас есть файл конфигурации, где прописано какая из фич включена/выключена и в коде существует проверка которая позволяет пропускать какую-то логику, например

if (configurationManager.getParameter("someFuncIsEnabled")) {
    // do some stuff
} else {
    // do default logic
}

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

  • Можем мержить и деплоить код, который еще не готов
  • A/B тесты
  • Шаринг кода между недоработанными фичами, за счет мержа всего кода в master

Branch By Abstraction

Trunk Based Development предлагает вместо создание ветки для фич, создавать ветку на изменение одной абстракции.

Представим, что у нас есть объект Car, у которой есть абстракция “передние колоса” и “задние колеса”, которые мы хотим заменить на другой тип колес. В случае с feature branch, мы бы разработали реализацию нового типа колес в 1 бранче, с Branch By Abstraction все немного сложнее.

Рассмотрим рисунок и шаги которые нам помогут раскрыть порядок действий при TBD подходе

cars trunk based development

  1. Создаем ветку, оборачиваем переднее колесо в абстракцию, отправляем Pull Request, мержим
  2. Создаем ветку, описываем новый тип передних колес и добавляем feature flag переключения типов колес, отправляем Pull Request, мержим
  3. Создаем ветку, оборачиваем заднее колесо в абстракцию, отправляем Pull Request, мержим
  4. Создаем ветку, описываем новый тип задних колес и добавляем feature flag переключения типов колес, отправляем Pull Request, мержим
  5. Включили в проде новый тип колес, убедились, что все ок
  6. Удаляем старые колеса отдельными Pull Request`ами

И что нам это дало?

  • Частые интеграции! Мы уже пришли ранее к тому что нужно часто интегрировать маленькие кусочки кода(CI), теперь при таком подходе можно делать "микрокусочки".
  • Постепенное изменение/рефакторинг кода. Вместо переделки всего разом, меняем постепенно, шарим изменения до того как закончим большую задачу.
  • Возможность переключения на другие фичи. В случае, если нужно переключиться на другую задачу, мы можем смежить последнее изменения и вернуться к доработке потом.

Continuous Code Review

Ревьювим чужие pull requests, сразу после того как отправили свой. Из-за этого что пулл реквесты маленькие(изменение одной абстракции), их ревью занимает не более чем пару минут, Если от создания пулл реквеста до аппрува прошло 10 минут, то это приемлемый результат, если больше 1 часа, то это считается очень плохим результатом.

Что нам дает концепт Continuous Code Review

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

Плюсы и минусы Trunk Based Development

Плюсы:

  • Позволяет быстро выполнять итерации и при этом поддерживать качество.
  • Хорошо работает в сценариях CI/CD.
  • Можно релизиться как можно чаще, в том числе несколько раз в день.

Минусы:

  • Лучше всего работает когда у вас команда состоит с опытных разработчиков.
  • Наполовину готовые функции, неправильно реализованными feature flag'ами, может вызвать проблемы.
  • Изначально может вызвать некоторые проблемы, если нет хорошего покрытия тестами или уверенности в стабильности системы.

Comments:

Please log in to be able add comments.