Webrium
Подписаться

dev и stage в большой команде: что показывает замер

Как крупные команды выбирают схемы ветвления и почему классические подходы часто не справляются

Из шести проектов с dev-ветками только один использует stageПроекты с dev/stageИспользуют stage

Ветки в больших командах: когда классические схемы перестают работать

Работа с ветками в 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.

Эти цифры рисуют картину, где трёхветочная схема (devstagemain) — скорее исключение, чем правило. Но у замера есть важные ограничения:

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

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

  3. Наличие ветки ≠ её активное использование Ветка может существовать годами, но не обновляться. Или обновляться, но не использоваться для релизов. Замер показывает только то, что ветку не удалили.

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

Почему трёхветочная схема ломается на практике

Трёхветочная схема предполагает, что фичи проходят три этапа проверки: сначала в 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: Основная ветка + релизные ветки

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

Требования:

  • Дисциплина слияний (если что-то попало в релизную ветку, оно должно быть готово к продакшену)
  • Явное решение о составе релиза
  • Частые подтягивания (релизная ветка должна быть синхронизирована с основной)

Преимущества:

  • Позволяет заморозить состав релиза
  • Подходит для редких релизов

Недостатки:

  • Требует дополнительных усилий по синхронизации
  • Может приводить к расхождению веток

Стенд на каждую фичу: как тестировать фичи в изоляции

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

Как это работает:

  1. Для каждой фичи создаётся отдельная ветка feature/issue-123
  2. Стенд собирается из основной ветки + ветка фичи
  3. При изменении основной ветки стенд пересобирается
  4. У стенда своя база данных (из обезличенного снимка)
  5. Внешние зависимости подменяются песочницами
  6. Доступ к стенду закрыт, индексация запрещена
  7. Стенд удаляется по слиянию фичи или по простою

Преимущества:

  • Фичи тестируются в изоляции
  • Нет конфликтов между фичами
  • Быстрая обратная связь

Недостатки:

  • Требует дополнительных ресурсов
  • Не проверяет сочетание фич
  • Требует автоматизации

Рабочий порядок для редких релизов

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

Процесс:

  1. Готовая фича сливается в основную ветку сразу
  2. То, что живёт дольше цикла, сливается выключенным за переключателем
  3. В день заморозки ветка релиза отрезается от основной
  4. Сборка артефакта один раз
  5. Тот же артефакт на стенд приёмки и в прод
  6. Тег прода, основная ветка подтягивается, ветка релиза удаляется
  7. Хотфикс режется от боевого тега и возвращается в основную и в открытую ветку релиза

Преимущества:

  • Нет вечных веток
  • Гарантия, что в продакшен попадёт именно то, что проверили
  • Простота процесса

Почему артефакт важнее порядка веток

При повышении слиянием то, что проверили, и то, что уехало в продакшен, — это разные объекты. После слияния в релизную ветку сверху лягут коммиты слияния, и артефакт соберётся уже из нового состояния.

Проблема: Если в коммитах слияния будет баг, он попадёт в продакшен, даже если на стенде всё работало.

Решение: Собирать артефакт один раз и повышать его по окружениям. Тогда то, что проверили, и то, что уехало, — это один и тот же объект.

Примеры команд

Как убедиться, что в продакшене нет ничего мимо основной ветки:

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 накопились неготовности, новая ветка не решит проблему
  • Следующий релиз вернёт ту же боль
  • Проблема не в количестве веток, а в том, как принимаются решения о составе релиза

Позиция редакции

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

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

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

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

С чем это связано

Метка над заголовком говорит, зачем туда идти: продолжить тему, перейти к практике или увидеть возражение.

Схема стыка веток: совпадение и расхождение dev, stage и masterСовпадаютРасходятся
Углубление

Когда dev, stage и master разошлись: как выкатывать фичи

Как избежать конфликтов при выкатке фич и сохранить синхронизацию между dev, stage и master — с примерами рабочих схем.

Разделение незавершённого кода и срочного исправления в продакшенеМусор в devФикс в master
Практика

Срочный фикс в master, когда в dev лежит несделанное

Как выкатить критичный багфикс в продакшен, не задев незавершённую разработку в dev и stage. Пошаговая схема для команд с тремя ветками.

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

Git-приёмы, которые перестают быть страшными

Как устроена история в Git, почему опасные команды не так страшны и как восстановить потерянную работу через reflog.

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

Деплой без кластера: что осталось живым

Как на практике деплоить без кластера — и почему однонодовые решения не масштабируются.

Письмо по вторникам

Один разбор недели и короткий список того, что изменилось. Без дайджестов на сорок ссылок.

Начните вводить — материалы появятся здесь.

выбрать · Enter открыть · Esc закрыть