Git не навязывает процесс: ветки дешёвые, делай что хочешь. Поэтому каждая команда выбирает модель ветвления — соглашение о том, какие ветки живут в проекте, откуда ветвиться и куда вливаться. Моделей придумано много, но в живых командах вы почти всегда встретите одну из четырёх — их и разберём. Знать их нужно и чтобы быстро включиться в процесс новой команды, и чтобы понимать, почему процессы такие разные.
Различает их одно число: сколько времени работа живёт в стороне от общей ветки — недели, дни или часы. Всё остальное — следствие.
Git Flow: тяжеловес эпохи релизов
main с тегами версий и develop живут всегда; feature, release и hotfix приходят и уходят. Каждая release и каждый hotfix обязаны влиться дважды: в main и обратно в develop, и забытое второе слияние возвращает в следующий релиз уже починенный баг.
Классика 2010 года: две долгоживущие ветки — main (только релизы, каждый помечен тегом) и develop (интеграция текущей разработки) — плюс три вида временных: feature/* (от develop, в develop), release/* (подготовка релиза: стабилизация, версии), hotfix/* (срочный фикс, отходит от main). Обе временные ветки возвращаются одинаково — и в main, и в develop: из main выходит релиз с тегом, а develop забирает то, что нашли и починили по дороге. Это видно и на схеме выше: от release и от hotfix идут по две линии, а не по одной.
Сильная сторона — параллельные версии: пока develop копит v2.4, release-ветка стабилизирует v2.3, а hotfix чинит v2.2 в проде. Слабая — церемониальность: много веток, много слияний, а забытая обратная заливка в develop — хоть из hotfix, хоть из release — классический источник регрессий, когда починенный в проде баг возвращается со следующим релизом.
Где уместен: коробочные продукты, мобильные приложения с релизными поездами, энтерпрайз с параллельной поддержкой версий. Для непрерывно деплоящихся веб-сервисов Git Flow сегодня избыточен, и это признал сам его автор: в 2020 году он дописал к исходной статье оговорку, что модель делалась под версии, которые выпускают редко, а для веб-приложений с непрерывной поставкой советовал что-то проще.
GitHub Flow: просто и вокруг PR
Одна долгая ветка, main, всегда готова к деплою. Каждая рабочая ветка живёт дни, вливается через pull request с ревью и зелёным конвейером, и слияние сразу означает выкат. Места для стабилизации отдельного релиза здесь нет, и это цена простоты.
Одна долгоживущая ветка — main, всегда готовая к деплою. Всё остальное — короткие ветки от main, вливаемые назад через pull request с ревью и зелёным конвейером. Влил — задеплоил.
Сильные стороны: минимальная церемония, скорость, естественная связка с код-ревью и CI. Слабость — нет штатного места для «стабилизации релиза» и параллельных версий: main всегда один.
Срочный фикс прода здесь ничем не отличается от обычной задачи, и в этом сила модели: ветка от main, правка, PR, зелёный конвейер, слияние, деплой. Отдельной ветки hotfix нет, потому что main и есть прод; разница только в приоритете ревью и в том, что такой PR принято держать на одну строку. Если сломавшее изменение известно, ещё быстрее git revert его коммита тем же PR, а починку делать уже без спешки.
Где уместен: веб-сервисы и команды с непрерывной поставкой — то есть большинство современных продуктовых команд. Если сомневаетесь, с чего начать, — начните с этого.
GitLab Flow: ветки под окружения
Тот же GitHub Flow наверху: короткие рабочие ветки вроде feature/checkout вливаются в main через merge request. Ниже долгие ветки под окружения: изменение продвигают слиянием main в staging, а после проверки staging в production. Ветка равна стенду: что в ней, то и развёрнуто, и откат это откат слияния.
GitHub Flow отвечает на вопрос «как код попадает в main» и молчит о том, что происходит между main и продом, когда выкатывают не сразу: сначала тестовый стенд, потом предпродакшен, потом прод. GitLab Flow дописывает этот хвост. Наверху та же механика: короткие ветки, merge request, ревью, зелёный конвейер. Ниже появляются долгоживущие ветки под окружения, и изменение продвигают по лестнице main → staging → production слияниями, всегда в одну сторону и всегда целиком. Коммитов прямо в staging или production нет: ошибку, найденную на стенде, чинят в main и продвигают заново, а само продвижение обычно делает конвейер по кнопке или по расписанию.
Сильная сторона — ответ на вопрос «что сейчас в проде» лежит в git, а не в панели деплоя: в проде ровно то, что в ветке production. У каждого окружения своя история, откат становится откатом слияния, а ручная приёмка на стенде получает законное место в процессе, которого в GitHub Flow нет.
Цена — продвижение это шаг, который кто-то должен сделать. Пропустили несколько, и staging с production отстают от main на недели, а потом одно слияние тащит в прод месяц чужих изменений разом, и от лестницы остаётся три разных продукта. Вторая ловушка — соблазн под давлением закоммитить починку прямо в production; одна такая правка ломает правило «ветка равна стенду», и её потом ищут неделями.
Где уместен: команды, у которых между main и продом стоит хотя бы один обязательный стенд с ручной приёмкой, и регламентированные выкаты, где нужно показать, что именно и когда ушло в прод.
Вторая форма GitLab Flow. Интеграция идёт в main, как в GitHub Flow, а под каждую выпущенную версию от него отходит своя release/2.3 с тегами. Исправление сначала попадает в main и только потом переносится в релиз через cherry-pick: так оно не потеряется в следующей версии. Обратных слияний нет, поэтому нет и забытой обратной заливки из Git Flow.
Вторая форма GitLab Flow нужна там, где живёт несколько версий одновременно, но Git Flow с его develop тяжёл. Интеграция по-прежнему идёт в main, а под каждую выпущенную версию от него отходит своя релизная ветка release/2.3, на ней ставят теги и в неё попадают только исправления. Правило одно и строгое: исправление сначала вливают в main, потом переносят в релиз через cherry-pick, а не наоборот. Так оно гарантированно окажется в следующей версии, а релизная ветка никогда не вливается обратно, и знаменитой забытой обратной заливки из Git Flow здесь не бывает по устройству. Когда версия перестаёт поддерживаться, ветку просто закрывают.
Где уместен: коробочные продукты и мобильные приложения с проверкой в магазине, где версия 2.3 у клиентов живёт, пока в main собирается 2.4, и её надо чинить отдельно.
Trunk-based: скорость на пределе
Все пишут в ствол маленькими порциями, прямо или через ветку на несколько часов. Недоделанная работа тоже попадает в main, но выключена фиче-флагом: код в проде, поведение нет. Держится это только на быстром конвейере и автотестах, без них ствол превращается в общий черновик.
Радикальное развитие той же идеи: все коммитят в main («ствол») очень маленькими порциями — либо напрямую, либо через ветки-однодневки. Интеграция происходит непрерывно, конфликты почти исчезают (нечему расходиться), скорость поставки максимальна.
Цена — зрелость инженерной культуры. Недоделанные фичи попадают в main и прячутся за фиче-флагами (код в проде, но выключен конфигом); без сильного автотестирования и дисциплины trunk-based превращается в хаос. У флагов своя цена, и она не видна в день первого флага. Каждый флаг это if в коде и две ветки поведения, которые надо тестировать обе; десять флагов дают тысячу сочетаний, и часть из них никто никогда не запускал. Флаг, оставленный после раскатки, превращается в мёртвый код, который боятся трогать, поэтому у флага с рождения есть срок жизни и задача на удаление, а в коде его держат в одном месте, а не размазывают по слоям. И срочный фикс в trunk-based это тоже флаг или revert: выключить фичу конфигом за секунды, а не откатывать релиз. Кто этим не управляет, через год получает вместо веток в Git те же ветки в конфигурации. Зато именно эта модель из года в год попадает в число признаков команд-лидеров в ежегодном отчёте DORA «State of DevOps»: короткоживущие ветки там устойчиво связаны и с высокой скоростью поставки, и со стабильностью.
Где уместен: команды с развитым CI, быстрым ревью и автотестами; крупные инженерные организации (Google живёт на монорепе со стволом).
Как выбирать
Вопросы, решающие выбор:
- Сколько версий поддерживаете одновременно? Несколько — Git Flow или релизные ветки GitLab Flow. Одну, в проде всегда свежая — GitHub Flow / trunk-based.
- Есть ли обязательные стенды между main и продом? Есть, с ручной приёмкой — GitLab Flow с ветками под окружения. Нет, деплой сразу из main — GitHub Flow.
- Как часто деплоите? Релизные поезда раз в месяц терпят церемонии; деплой по многу раз в день требует лёгкой модели.
- Насколько зрелы автотесты и ревью? Trunk-based без них опасен; GitHub Flow — рабочая середина.
И главное: модель — командное соглашение, а не догма. Реальные процессы часто гибридны («GitHub Flow плюс release-ветка перед мажорной версией») — важно, чтобы соглашение было явным и одинаково понималось всеми. Как ветвление стыкуется с конвейером доставки и версионированием — в статье про ветки и релизный цикл.
Переход с модели на модель случается чаще, чем кажется: команда на Git Flow, у которой релизы стали еженедельными, а develop превратился в источник конфликтов. Переходят не одним днём, а в три шага. Сначала довыпускают открытые release-ветки и сливают всё из develop в main, чтобы обе ветки указывали на один снимок. Потом объявляют main единственной долгой веткой: включают на ней защиту, переводят конвейер деплоя на неё, а develop удаляют, иначе кто-нибудь по привычке продолжит вливать туда. И наконец переучивают hotfix: он становится обычным PR в main, а параллельные версии, если они нужны, получают релизные ветки по второй форме GitLab Flow вместо develop. Имена веток при этом не меняются: схема тип/задача-суть из статьи про ветки одинаково работает во всех четырёх моделях.
Глубже: большие репозитории: монорепозиторий, подмодули, LFSрасширенное
Trunk-based выше ссылается на монорепозиторий Google, где весь код компании лежит в одном хранилище. Это не «обычный» репозиторий побольше, а отдельное решение со своей ценой.
Монорепозиторий даёт атомарные изменения сразу в нескольких сервисах одним коммитом, общий стиль и один конвейер, но требует инструментов: сборки только затронутого (Bazel, Gradle с кешем, Nx), прав на каталоги через CODEOWNERS и терпения к тому, что git clone тянет всё. Полирепозиторий, по репозиторию на сервис, проще в начале и превращает общее изменение в серию связанных PR.
Два инструмента для промежуточных случаев. Подмодуль (git submodule add <url> libs/common) вкладывает чужой репозиторий как указатель на конкретный коммит: обновляется он только явным git submodule update --remote, и половина бед команд с подмодулями это забытый после клонирования git submodule update --init. Git LFS решает другую беду, большие бинарные файлы: в истории лежит короткий указатель, а сам файл скачивается с отдельного хранилища по требованию (git lfs track "*.psd"). Без него репозиторий с парой сотен картинок в истории растёт на гигабайты, и каждый клон тянет их все.
Коротко
- Git Flow: main+develop+feature/release/hotfix — для параллельных версий и релизных поездов; для непрерывного деплоя избыточен.
- GitHub Flow: один main + короткие ветки через PR — дефолт современных продуктовых команд.
- GitLab Flow: тот же верх плюс долгие ветки под окружения (main → staging → production) или релизные ветки с cherry-pick исправлений; ветка равна стенду.
- Trunk-based: мини-порции в ствол + фиче-флаги — максимальная скорость при зрелых тестах и культуре.
- Чем дольше ветка живёт в стороне от main, тем дороже слияние: отсюда и разница моделей.
- Выбор определяют: число поддерживаемых версий, частота деплоя, зрелость автоматизации.
- Модель — явное командное соглашение; гибриды нормальны.
- Монорепозиторий это инструменты сборки и права на каталоги, а не большой репозиторий; чужой код подключают подмодулем, большие бинарники держат в LFS.
- Срочный фикс в GitHub Flow это обычный PR в
mainс приоритетом илиrevert; в trunk-based флаг выключают конфигом. У флагов своя цена: сочетания, мёртвый код, обязательный срок жизни и задача на удаление. - Переход с Git Flow: довыпустить релизы, слить
developвmain, защититьmainи удалитьdevelop, hotfix превратить в обычный PR.
Что почитать дальше
- Ветки и слияние: merge и конфликты — механика, которой ежедневно пользуется любая из четырёх моделей.
- Pull request и код-ревью — механика, на которой стоят GitHub Flow и trunk-based.
- Ветки и релизный цикл — продолжение темы на стороне CI/CD: версии, теги, GitOps.
- CI/CD-конвейер — автоматика, делающая лёгкие модели возможными.