Давным-давно, ещё во времена больших сотовых телефонов и динозавров, когда PERL был перспективным языком программирования, наши инструменты были очень простыми и надежными:

  • PUTTY и FTP были основным способом обмена кодом и ведения совместной разработки.

  • Разработку вели в одиночку или малыми командами.

  • Хотфиксы мы катили, сразу редактируя файлы в VIM на prod машинах.

Но всё изменилось с приходом систем контроля версий: GIT, SVN, Mercurial, etc. И появление этих инструментов открыло путь к крупным проектам, большим командам и сложным продуктам.

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

Сегодня я расскажу про свой любимый подход к разработке Trunk Base Development, сравню его с другими моделями ветвления и подсвечу его достоинства и нюансы.

Краткий обзор трёх моделей ветвления: Central Workflow, Git Flow, Trunk Based Development, с акцентом на моего фаворита — Trunk Based Development.

Central Workflow

Просто комит и сразу в мастер. А ветки для слабаков.

Цепочка комитов в master-ветку
Цепочка комитов в master-ветку

В итоге Central Workflow подходит:

  • Для небольших проектов (pet-проектов).

  • Для команд из 2-3 разработчиков.

  • Когда мастер сломан.

Git Flow

Процесс — это все! Сложный процесс со сложной моделью ветвления.

Так выглядит этот процесс у автора https://nvie.com/posts/a-successful-git-branching-mode
Так выглядит этот процесс у автора https://nvie.com/posts/a-successful-git-branching-mode

Чтобы было проще, постараюсь изложить процесс в виде цикла разработки фичи:

Исходное состояние
Исходное состояние

Для создания фичи, вы создаете ветку feature. Ветвите вы её от ветки develop:

Сделали ветку feature, в которой будет вестись разработка
Сделали ветку feature, в которой будет вестись разработка

Ветка создана, можно начинать разработку.

Вы поработали, сделали несколько комитов
Вы поработали, сделали несколько комитов

Ваша команда долго и упорно готовила фичу — теперь всё готово! Но другие команды разработки тоже делают свои проекты. Допустим, готовые фичи уже слили в develop-ветку, при этом ваша ветка сильно отстала.

[Первый раз] Вы решаете конфликты и сливаете ветку в develop:

Время релиза! Вы р��шили поделится своей фичей с пользователями. Создаётся ветка release от вашего комита.

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

Релиз стабилизирован. Сливаем его в master c тегом v1.0.0 и катим на prod. Хотфиксы тоже надо слить в develop-ветку. За это время develop опять ушёл вперед.

[Второй раз] Вы решаете конфликты и сливаете ветку в develop:

На prod мы неожиданно ловим еще несколько ошибок, которые важно пофиксить. Вы делаете хотфикс на prod и ветку v1.0.1.

Но новый хотфикс тоже нужно положить обратно в develop-ветку. За это время develop опять ушёл вперед.

[Третий раз] Вы решаете конфликты и сливаете ветку в develop:

В итоге Git Flow:

  • Очень сложно и запутано.

  • Много конфликтов в процессе.

  • Долгий релизный цикл, который плохо подходит для CI\CD.

  • Подходит для ПО с классическим релейным циклом (параллельная работа над разными верс��ями, релиз раз в месяц на дискетах).

Trunk Based Development

trunkbaseddevelopment.com
trunkbaseddevelopment.com

Характеризуется всего тремя типами веток и итеративным подходом к разработке фичи (привет, Scrum).

Постараюсь изложить его в виде цикла разработки фичи:

Исходное состояние
Исходное состояние

Для создания фичи, вы создаете ветку feature. Ветвите вы её от ветки master:

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

Сливаете фича-ветку в master. Ваш функционал может быть закрыт feature-toggle или if false { ... } — «сырой» функционал не должен быть доступен пользователю.

Важно!

Так как с момента ветвления до момента слияния вашей фича-ветки прошло очень мало времени, master не успеет далеко уйти и у вас будет минимум или полное отсутствие конфликтов при слиянии. При этом вы «застолбили» для своей фичи место, подсветили другим командам, к примеру, интерфейсы, которые планируете имплементить. И другие команды будут сразу учитывать это в своей работе.

А ещё у вас очень маленькие PR\MR, которым можно легко и быстро провести code-review. Знаете же эту классическую проблему — большие PR смотрят долго и некачественно.

У вас может быть организован процесс непрерывного деплоя, или деплоя по расписанию, в prod. Так как в master не сливают сложные и плохо протестированные изменения — master остаётся чистым, готовым к релизам.

Вы продолжаете работать над своей фичей в новой итерации — продолжаете её и углубляете.

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

В итоге, TBD — это:

  • Ветки, которые живут несколько дней.

  • Feature-flags для закрытия «сырого» функционала.

  • Continuous Сode Review. Код-ревью фича проходит каждую итерацию — дифф маленький, ревью делается быстро.

  • Чистый мастер, готовый к релизу в любой момент.

Плюсы TBD:

  • Минимум конфликтов при разработке.

  • Готовность к релизам в любой момент без подготовки.

  • Очень быстрая и качественная обратная связь на PR\MR.

Минусы TBD:

  • Не подходит, если в команде много junior-разработчиков. Ребятам гораздо легче делать\ревьювить готовую фичу целиком, чем разделить работу на этапы и держать прошлые итерации в голове.

  • Нужно доверять комитерам, иначе будут висеть недоделанные фичи и будет непонятно, кто и когда их доделает.

  • Если потребуется revert — будет больно. Мастер постоянно бежит вперед и revert функционал спустя пару дней уже тяжело. Проще исправить или удалить руками.

Кому подходит TBD:

  • Опытным командам с небольшим количеством junior-разработчиков.

  • Большим командам, которые параллельно работают над большим количеством фич.

  • Приложениям с долгим циклом регрессивного тестирования.

  • Проектам с непрерывным релизным циклом.

Для кого TBD не очень хорошо подходит:

  • Junior-командам.

  • OpenSource-проектам.

  • Проектам с жестким (классическим) релизным циклом с отгрузкой софта клиентам на дискетах.

Почему всё же TBD

Time To Market

Использование такого подхода дает огромный прирост к TTM метрике.

Короткоживущие ветки позволяют вам экономить время на конфликты при слиянии, а когда нет конфликтов — и нервы экономишь. Багов после решения конфликтов возникает гораздо меньше.

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

Чистый мастер позволяет вам делать релизы настолько часто, насколько нужно. Релизы перестают быть переполнены фичами, а ещё пропадают «ждуны», которые просят задержать релиз.

Раньше при релизе в чатах постоянно такое мелькало
Раньше при релизе в чатах постоянно такое мелькало

Релизы бэкенда-монолита:

Релизы приложений:

В таблицах примеры того, как ускорились релизы в Авито за несколько лет. Цифры не самые свежие, но честные.

Вывод

Все фломастеры на вкус разные, но особенно вкусные те, что цвета Trunk Based.

Для Авито эта модел�� ветвления подошла лучше всего: она позволила сильно ускорить разработку, внедрить быстрый релизный цикл, меньше ловить конфликтов на слиянии, упростить жизнь разработчикам.

Она гораздо проще, чем многие другие модели, но имеет свои ограничения. Выбирайте с умом!

Полезные ссылки