open atlas
↑ К треку
Git: от нуля до сеньора GIT · 06 · 02

Git-flow

Git-flow держит две долгоживущие ветки — main (выпущенный) и develop (интеграция) — плюс короткоживущие feature/, release/ и hotfix/. Силён в версионных релизах и нескольких живых версиях, но множество веток делает его тяжёлым для непрерывной поставки; legacy для веба.

GIT Middle ◷ 17 min
Уровень
ОсновыJuniorMiddleSenior

В 2010 году Винсент Дриссен опубликовал «A successful Git branching model», и десятилетие это был тот самый ответ, когда команда спрашивала «как нам пользоваться ветками?». У него есть имя — git-flow, диаграмма, которую видел каждый, и даже набор вспомогательных команд. Это также самый структурированный, самый церемонный workflow, который тебе встретится: пять видов веток и строгие правила, как каждая из них сливается.

К концу этого урока ты сможешь проследить фичу, релиз и хотфикс сквозь структуру веток git-flow и точно сказать, для какого типа проекта он по-прежнему верный выбор, а какой он, наоборот, активно тормозит.

Цель

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

1

У git-flow две долгоживущие ветки: main и develop. main держит только выпущенный, продакшен-код — каждый коммит на ней — это отгруженная версия, обычно помеченная тегом (v1.4.0). develop — ветка интеграции: она копит готовые фичи, нацеленные на следующий релиз, но ещё не отгруженные. Это разделение — сердце git-flow. main отвечает на «что в продакшене», develop отвечает на «что будет в следующем релизе», и эти две никогда не одна и та же ветка. Всё остальное в git-flow — короткоживущая ветка, которая в итоге сливается в одну или обе из них.

2

Фичи ответвляются от develop и сливаются обратно в develop. Ветка feature/* — это место, где происходит одна единица новой работы. Она начинается с текущей верхушки develop и, когда отревьюена и готова, сливается обратно в develop — никогда напрямую в main.

git checkout develop
git checkout -b feature/user-search
# ... коммиты ...
git checkout develop
git merge --no-ff feature/user-search
git branch -d feature/user-search

Флаг --no-ff (no fast-forward) здесь идиоматичен: он принуждает создать merge-коммит, так что фича остаётся видна в истории как сгруппированная единица, а не сплющивается в develop. Фичи никогда не трогают main напрямую — продакшен-код приходит только через релиз.

3

Релизная ветка стабилизирует develop, затем сливается в ОБЕ — main и develop. Когда в develop накопилось достаточно фич для релиза, ты нарезаешь ветку release/* от неё. На этой ветке ты делаешь только релизную работу — поднятие версии, последние правки багов, changelog — но не новые фичи. Когда она готова, она сливается в main (и получает тег с версией), а также обратно в develop, чтобы поздние правки не потерялись:

git checkout develop
git checkout -b release/1.5.0
# поднять версию, починить релизные баги ...
git checkout main
git merge --no-ff release/1.5.0
git tag -a v1.5.0 -m "Release 1.5.0"
git checkout develop
git merge --no-ff release/1.5.0
git branch -d release/1.5.0

Двойное слияние — та часть, которую забывают. Пропусти слияние обратно в develop — и твои релизные правки исчезнут из следующего цикла разработки.

4

Хотфиксы ответвляются от main, потому что именно там живёт продакшен. Критический для продакшена баг не может ждать следующего релизного цикла через develop. Ветка hotfix/* начинается с самой main, чинит одну вещь, затем — как релиз — сливается в обе: main (тег как патч, v1.5.1) и develop (чтобы правка не откатилась в следующем релизе):

git checkout main
git checkout -b hotfix/1.5.1
# починить баг ...
git checkout main
git merge --no-ff hotfix/1.5.1
git tag -a v1.5.1 -m "Hotfix 1.5.1"
git checkout develop
git merge --no-ff hotfix/1.5.1

Это настоящая сила git-flow: чистый, отдельный путь для срочных продакшен-правок, который никогда не тащит за собой недоделанную работу из develop.

Почему это работает

Оригинальный пост поставлял расширение командной строки git flow (git flow init, git flow feature start, git flow release finish), автоматизирующее ровно эти последовательности ветвлений и слияний. Хелпер удобен, но необязателен — git-flow это соглашение, и каждая команда выше — обычный git. Риск опираться на хелпер в том, что инженеры выучивают обёртку, не понимая нижележащих слияний, а потом паникуют, когда что-то идёт не по сценарию. Знание сырых операций — это то, что позволяет тебе восстановиться, когда обёртка не подходит.

Разбор примера

Отгрузка 1.5.0, затем патч в тот же день.

В твоём develop три слитые фичи. В пятницу ты нарезаешь release/1.5.0, поднимаешь версию, и QA находит один баг на релизной ветке — ты чинишь его там. В понедельник релиз сливается в main, ты тегируешь v1.5.0, деплоишь и сливаешь release/1.5.0 обратно в develop, чтобы пятничная правка жила. Во вторник клиент натыкается на падение в продакшене. Ты не трогаешь develop (где уже наполовину готовы новые фичи 1.6). Вместо этого ты ответвляешь hotfix/1.5.1 от main, чинишь падение, сливаешь в main, тегируешь v1.5.1, деплоишь и сливаешь хотфикс ещё и в develop.

Заметь, что git-flow тебе купил: незавершённая работа над 1.6 в develop никогда не приближалась к продакшену, хотфикс отгрузился ровно из того кода, что был живым, и и релизная правка, и хотфикс сохранились для следующего цикла. Это чистое разделение «что живое» и «что следующее» — вся причина существования git-flow.

Частая ошибка

Слабость git-flow — оборотная сторона его силы: он тяжёлый. Две долгоживущие ветки плюс три вспомогательных типа означают постоянное межветочное слияние, а путь develop-затем-release-затем-main добавляет задержку между «фича готова» и «фича живая». Для веб-приложения, деплоящегося много раз в день, эта церемония — чистые накладные расходы: нет никакой «версии 1.5.0», есть просто main и продакшен. Сам Дриссен добавил в 2020 году примечание, что git-flow задумывался для версионного софта и что командам на непрерывной поставке стоит брать модель попроще. Хвататься за git-flow на непрерывно деплоящемся веб-приложении — самая частая ошибка в выборе workflow.

Проверь себя
Викторина

В git-flow от какой ветки стартует hotfix-ветка и почему?

Итог

Git-flow использует две долгоживущие ветки — main для выпущенного кода и develop для интеграции — плюс короткоживущие feature/, release/ и hotfix/. Фичи текут через develop; ветка release стабилизируется и сливается в обеmain (с тегом) и develop; hotfix ответвляется от main и так же сливается в обе. Его сила — чистая поддержка версионных релизов и нескольких продакшен-версий; его слабость — вес всех этих долгоживущих веток, который борется с непрерывной поставкой. Поэтому он всё чаще legacy для веб-приложений и лучше всего подходит для библиотек, десктопа и прошивок. Дальше ты увидишь его почти противоположность: GitHub flow с единственной долгоживущей веткой.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 4 завершено

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.