Рабочий процесс Gitflow
Изучите рабочий процесс Gitflow: ветки main, develop, feature, release и hotfix — и когда эта структура полезна для версионных продуктов.
Обзор
Gitflow — это структурированная модель ветвления, популяризованная Винсентом Дриссеном в 2010 году. Она разработана для проектов с запланированными версионными релизами. Вместо одной интеграционной ветки используются две долгоживущие ветки и три вида вспомогательных веток, каждая с определённой целью. Структура делает управление релизами явным, но требует большего количества формальностей.
Две долгоживущие ветки
Эти две ветки существуют на протяжении всей жизни проекта — их никогда не удаляют.
- main содержит готовый к продакшену код. Каждый коммит в
mainсоответствует выпущенной версии и обычно помечается тегом (например,v1.4.0). Если нужно узнать, что именно работает в продакшене, достаточно переключиться наmain. - develop — интеграционная ветка, в которой накапливаются завершённые функции между релизами. Она всегда содержит последние готовые изменения, предназначенные для следующего релиза, но эти изменения не обязательно стабильны.
Поскольку обе ветки постоянные, связь между ними никогда не сбрасывается: develop всегда «опережает» main на то, что ещё не было выпущено.
Три вспомогательные ветки
Вспомогательные ветки — короткоживущие. Каждая создаётся для одной цели, вливается по завершении этой цели и затем удаляется. Соглашения об именовании (feature/, release/, hotfix/) делают их роль очевидной в выводе git branch.
Ветки функций (feature)
Ветки функций ответвляются от develop и сливаются обратно в develop. Они содержат работу над предстоящим функционалом и никогда не взаимодействуют с main напрямую — отдельная функция никогда не выпускается самостоятельно; она поставляется в составе следующего версионного релиза.
git switch develop
git switch -c feature/search # create + check out feature/search
# ...work and commit...
git switch develop
git merge feature/search # fold the feature into develop
git branch -d feature/search # delete it once mergedКоманда git switch -c <name> создаёт ветку из текущей и сразу переключается на неё — это современный аналог git checkout -b. Полное описание команды см. в Git switch. Если держать ветки функций короткоживущими, они не будут сильно расходиться с develop, что уменьшает конфликты слияния.
Ветки релиза (release)
Ветки релиза ответвляются от develop, когда та полностью готова по функциональности для выпуска. Они предназначены только для финальной доработки — обновления версий, написания примечаний к релизу и исправления последних багов — пока develop остаётся открытой для функций следующего цикла.
Когда релиз готов, ветка вливается в оба места:
- в
main, где помечается тегом с номером версии; и - обратно в
develop, чтобы исправления, внесённые в ветке релиза, не были потеряны.
git switch -c release/1.4.0 develop
# ...bump version, fix last bugs, write release notes...
git switch main
git merge --no-ff release/1.4.0 # record an explicit merge commit
git tag -a v1.4.0 -m "Release 1.4.0"
git switch develop
git merge --no-ff release/1.4.0 # carry fixes back into develop
git branch -d release/1.4.0Флаг --no-ff (без fast-forward) заставляет Git создавать коммит слияния, даже если возможна ускоренная перемотка (fast-forward). Это позволяет сохранить релиз как единую, видимую точку в истории, а не «сгладить» её.
Ветки хотфиксов (hotfix)
Ветки хотфиксов ответвляются от main, чтобы срочно исправить баг в продакшене — не дожидаясь готовности текущей работы в develop к выпуску. Как и ветки релиза, они вливаются в оба места: в main (с тегом с увеличенным патч-номером версии) и в develop, чтобы исправление присутствовало и в будущих релизах.
git switch -c hotfix/1.4.1 main
# ...fix the bug and commit...
git switch main
git merge --no-ff hotfix/1.4.1
git tag -a v1.4.1 -m "Hotfix 1.4.1"
git switch develop
git merge --no-ff hotfix/1.4.1 # don't reintroduce the bug later
git branch -d hotfix/1.4.1Забыть о втором слиянии — обратно в develop — классическая ошибка в Gitflow: баг снова появляется в следующем релизе, потому что исправление было применено только в main.
Когда использовать Gitflow
Gitflow отлично подходит, когда вы выпускаете отдельные версионные релизы — настольные приложения, библиотеки, мобильные приложения, проходящие проверку в магазинах, или всё, что имеет поддерживаемые номера версий и требует периодических экстренных патчей. Явные ветки релиза и хотфикса дают чёткое место для стабилизации и исправления продакшена без вмешательства в текущую разработку. Необходимость поддерживать несколько выпущенных версий одновременно — главный признак того, что структура Gitflow себя оправдает.
Полный цикл релиза с высоты птичьего полёта
Собирая всё воедино, одна версия проходит через ветки следующим образом:
- Разработчики создают ветки
feature/*отdevelop, реализуют функциональность и сливают каждую обратно вdevelop. - Когда
developсодержит достаточно для релиза, от неё создаётся веткаrelease/x.y.0для финальной стабилизации. - Ветка релиза вливается в
main, получает тегvx.y.0и сливается обратно вdevelop. - Если в продакшене возникает проблема, ветка
hotfix/x.y.zсоздаётся отmain, получает тег и вливается как вmain, так и вdevelop.
Таким образом, main продвигается исключительно через слияния релизов и хотфиксов, и каждый её коммит — это готовая к поставке, помеченная тегом версия.
Компромиссы
Эта структура — одновременно и слабость Gitflow. Множество типов веток создаёт дополнительные накладные расходы, а долгоживущая ветка develop может сильно разойтись с main, что делает слияния болезненными. Долгоживущие ветки поощряют крупные, редкие интеграции — противоположность тому, чего требует непрерывная поставка. Команды, выпускающие изменения много раз в день, обычно считают Gitflow слишком громоздким и предпочитают более простой подход с ветками функций или trunk-based разработкой, где работа непрерывно интегрируется в одну ветку. Выбирайте Gitflow тогда, когда ваши приоритеты — периодичность релизов и поддержка нескольких версий параллельно, а не максимальная скорость развёртывания.
Сравните его с альтернативами, прежде чем принимать решение: рабочий процесс с форками для вклада в open-source проекты и обычные ветки функций для большинства веб-приложений, развёртываемых из одной линии.