Ветки в больших командах: когда классические схемы перестают работать
Работа с ветками в Git — это не просто техническая рутина, а инструмент управления процессом разработки. Когда команда маленькая, можно обойтись одной основной веткой и короткими фичами. Но когда команда разрастается, начинают появляться дополнительные ветки: dev, stage, релизные, хотфиксы. Эти ветки обещают порядок, но на практике часто приводят к новым проблемам. Мы измерили, как реальные проекты используют эти ветки — и почему они не всегда решают заявленные задачи.
Данные: 44 публичных репозитория на GitHub с более чем 5000 звёзд, замеренные на момент написания статьи.
Что показывают цифры — и почему они неполные
Измерения дали девять ключевых чисел о том, как популярные проекты организуют ветки:
- Постоянную ветку
devилиdevelopдержат 6 репозиториев из 44. - Ветку
stageилиstaging— всего 1 из 44. - Ветки релизов используют 15 проектов, хотфиксов — 20,
feature/*— 17. - Ни
dev, ниstageнет у 38 из 44. При этом из шести проектов сdevчетверо всё равно режут релизные ветки — то естьdevу них не заменяет релизную ветку, а существует параллельно. - 11 проектов обходятся схемой «основная ветка + релизные ветки», без
dev. - Медиана числа веток — 14, но разброс огромен: девять проектов держат единственную ветку, четверть — больше восьмисот.
- У 24 из 44 основная ветка называется
main.
Эти цифры рисуют картину, где трёхветочная схема (dev → stage → main) — скорее исключение, чем правило. Но у замера есть важные ограничения:
-
Публичные репозитории ≠ корпоративная разработка В открытых проектах меньше бюрократии, чаще выкатки, проще откаты. В корпоративной среде могут быть другие требования: долгие согласования, внешние зависимости, сертификация.
-
Библиотеки ≠ разворачиваемые продукты Библиотеки проще тестировать в изоляции, у них меньше зависимостей от окружения. Продукты с базами данных, внешними API и пользовательскими интерфейсами требуют более сложных схем.
-
Наличие ветки ≠ её активное использование Ветка может существовать годами, но не обновляться. Или обновляться, но не использоваться для релизов. Замер показывает только то, что ветку не удалили.
-
Выборка не случайна Мы брали популярные проекты с большим количеством звёзд. В менее известных репозиториях схемы могут отличаться.
Почему трёхветочная схема ломается на практике
Трёхветочная схема предполагает, что фичи проходят три этапа проверки: сначала в dev, потом в stage, и только потом в main. На бумаге это выглядит логично, но на практике эта схема начинает давать сбои, когда в команде появляется больше десятка разработчиков.
Проблема 1: Решение о релизе принимается молча
Когда фича сливается в dev, это не значит, что она попадёт в релиз. Решение о том, какие фичи попадут в следующий релиз, принимается позже — когда кто-то решает слить dev в stage. Но это решение:
- Принимается в одиночку, без обсуждения
- Часто не документируется
- Может быть отменено в последний момент
В результате готовые фичи могут застрять в dev из-за одной неготовой. А если в dev накопится слишком много неготовностей, релиз может задержаться на недели.
Проблема 2: Вечные ветки расходятся
Чем больше людей работают над проектом, тем больше хотфиксов и срочных исправлений. Каждый хотфикс — это отдельная ветка, которая сливается напрямую в main, минуя dev и stage. В результате:
devиstageначинают отставать отmain- Их приходится постоянно подтягивать
- Чем больше таких подтягиваний, тем выше риск конфликтов
Со временем расхождение между ветками становится настолько большим, что их синхронизация превращается в отдельную задачу.
Проблема 3: stage не заменяет приёмку
stage часто воспринимают как аналог стенда приёмки, но это не так:
- На
stageнет реальных пользователей - Нет нагрузки, характерной для продакшена
- Нет реальных данных
- Нет внешних зависимостей
Баги, которые проявляются только под нагрузкой или на реальных данных, на stage не заметят. А если баг всё-таки найдут, его придётся исправлять уже в трёх местах: в dev, stage и main.
Два подхода: короткие фичи против релизных веток
Есть два принципиально разных подхода к работе с ветками, каждый со своими плюсами и минусами.
Подход 1: Одна основная ветка, короткие фичи
В этом подходе все фичи сливаются в основную ветку как можно быстрее. Незрелые фичи прячутся за переключателями, а выкатка происходит несколько раз в день.
Требования:
- Частые выкатки (несколько раз в день)
- Хорошая автоматизация тестирования
- Дисциплина с переключателями (неготовые фичи должны быть выключены по умолчанию)
Преимущества:
- Нет вечных веток
- Нет расхождения между ветками
- Быстрая обратная связь
Недостатки:
- Требует высокой дисциплины
- Не подходит для редких релизов
Подход 2: Основная ветка + релизные ветки
В этом подходе к основной ветке добавляются ветки окружений или релизов. В эти ветки сливают только вперёд, и в них никогда не коммитят напрямую.
Требования:
- Дисциплина слияний (если что-то попало в релизную ветку, оно должно быть готово к продакшену)
- Явное решение о составе релиза
- Частые подтягивания (релизная ветка должна быть синхронизирована с основной)
Преимущества:
- Позволяет заморозить состав релиза
- Подходит для редких релизов
Недостатки:
- Требует дополнительных усилий по синхронизации
- Может приводить к расхождению веток
Стенд на каждую фичу: как тестировать фичи в изоляции
Если команда хочет тестировать фичи независимо друг от друга, можно поднять стенд на каждую фичу. Стенд собирается из основной ветки плюс ветка фичи.
Как это работает:
- Для каждой фичи создаётся отдельная ветка
feature/issue-123 - Стенд собирается из основной ветки + ветка фичи
- При изменении основной ветки стенд пересобирается
- У стенда своя база данных (из обезличенного снимка)
- Внешние зависимости подменяются песочницами
- Доступ к стенду закрыт, индексация запрещена
- Стенд удаляется по слиянию фичи или по простою
Преимущества:
- Фичи тестируются в изоляции
- Нет конфликтов между фичами
- Быстрая обратная связь
Недостатки:
- Требует дополнительных ресурсов
- Не проверяет сочетание фич
- Требует автоматизации
Рабочий порядок для редких релизов
Если команда выкатывает раз в две-три недели, а хотфиксы делает когда угодно, можно обойтись двумя постоянными ветками: основной и текущей веткой релиза.
Процесс:
- Готовая фича сливается в основную ветку сразу
- То, что живёт дольше цикла, сливается выключенным за переключателем
- В день заморозки ветка релиза отрезается от основной
- Сборка артефакта один раз
- Тот же артефакт на стенд приёмки и в прод
- Тег прода, основная ветка подтягивается, ветка релиза удаляется
- Хотфикс режется от боевого тега и возвращается в основную и в открытую ветку релиза
Преимущества:
- Нет вечных веток
- Гарантия, что в продакшен попадёт именно то, что проверили
- Простота процесса
Почему артефакт важнее порядка веток
При повышении слиянием то, что проверили, и то, что уехало в продакшен, — это разные объекты. После слияния в релизную ветку сверху лягут коммиты слияния, и артефакт соберётся уже из нового состояния.
Проблема: Если в коммитах слияния будет баг, он попадёт в продакшен, даже если на стенде всё работало.
Решение: Собирать артефакт один раз и повышать его по окружениям. Тогда то, что проверили, и то, что уехало, — это один и тот же объект.
Примеры команд
Как убедиться, что в продакшене нет ничего мимо основной ветки:
git branch -r --merged origin/main | grep -v "origin/main$"
Как нарезать ветку релиза:
git checkout -b release-current main
Как вернуть хотфикс:
git checkout -b hotfix-issue main
# ... исправления ...
git checkout main
git merge --no-ff hotfix-issue
git checkout release-current
git merge --no-ff hotfix-issue
Как собрать стенд из основной ветки плюс ветка:
git checkout -b feature-issue
# ... работаем ...
git push origin feature-issue
# Стенд собирается из main + feature-issue
Тупик: ещё одна ветка или ещё один стенд
Когда команда сталкивается с проблемами в релизном процессе, первое, что приходит в голову, — добавить ещё одну ветку или ещё один стенд. Но это лечит симптом, а не причину.
Почему это не работает:
- Если в
devнакопились неготовности, новая ветка не решит проблему - Следующий релиз вернёт ту же боль
- Проблема не в количестве веток, а в том, как принимаются решения о составе релиза
Позиция редакции
В большинстве случаев лучше обходиться без промежуточных веток и полагаться на короткие фичи, частую выкатку и стенды на каждую фичу. Но есть важное условие, при котором эта позиция неверна:
Если приёмка обязательна и длинная (например, недельная) или выкатка требует внешней сертификации (например, для медицинского ПО), ветка окружения снова начинает окупаться.
В таких случаях ветка окружения позволяет заморозить состав релиза и провести все необходимые проверки, не блокируя разработку новых фич.
Главное — не количество веток, а то, как команда принимает решения о том, что попадёт в релиз. Если решения принимаются молча и в одиночку, никакие ветки не спасут от хаоса. Если же есть явный процесс принятия решений, даже одна ветка может быть достаточной.