Files

29 KiB
Raw Permalink Blame History

Git Flow: правила разработки в команде

Назначение

Этот документ описывает принятый в команде порядок работы с Git Flow:

  • какие ветки используются;
  • от каких веток создавать новые;
  • куда вливать изменения;
  • как работать с feature, release, hotfix;
  • как работать с зависимыми feature;
  • как синхронизировать локальные ветки;
  • как безопасно публиковать изменения;
  • что делать через Pull Request.

Цель — сделать историю изменений предсказуемой и избежать ситуаций, когда изменения случайно попадают не в ту ветку.


1. Основная модель веток

В классическом Git Flow используются две основные долгоживущие ветки:

  • main — код, находящийся в production;
  • develop — основная ветка текущей разработки.

Временные ветки:

  • feature/* — разработка новой функциональности;
  • release/* — подготовка релиза;
  • hotfix/* — срочное исправление production;
  • bugfix/* — исправление ошибок в процессе разработки;
  • support/* — поддержка старых версий, если это необходимо проекту.

Базовая схема:

                          feature/*
                         /        \
                        /          \
                       /            \
main ─────────────────●──────────────●─────────────
                      ↑              ↑
                      │              │
                   release        hotfix
                      │              │
                      └──────┐ ┌─────┘
                             ↓ ↓
develop ────────────────●────●─●──────────────────
                        ↑
                        │
                     feature

Главное правило:

feature/*  → develop
release/*  → main
release/*  → develop
hotfix/*   → main
hotfix/*   → develop

2. Что является источником для каждой ветки

Feature

Feature создаётся от:

develop → feature/*

Пример:

git flow feature start user-profile

Получается:

develop
   \
    feature/user-profile

Новые feature по умолчанию не создаются от main.


Release

Release создаётся от:

develop → release/*

Пример:

git flow release start 2.4.0

Получается:

develop
   \
    release/2.4.0

Release используется для подготовки уже готового набора изменений к production.

В release обычно не добавляют новые большие функциональные возможности.


Hotfix

Hotfix создаётся от:

main → hotfix/*

Пример:

git flow hotfix start 2.4.1

Используйте hotfix, когда проблема уже находится в production и исправление нельзя ждать до следующего обычного релиза.


Bugfix

bugfix используется для исправления ошибок в процессе разработки.

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

Пример:

git flow bugfix start fix-registration

3. Основной рабочий цикл Feature

Обычная разработка выглядит так:

develop
   │
   ├── feature/login
   │
   ├── feature/payment
   │
   └── feature/profile
            │
            └────────→ develop

Шаг 1. Обновить develop

Перед началом работы необходимо синхронизировать локальный develop:

git checkout develop
git pull origin develop

Шаг 2. Создать feature

git flow feature start user-profile

Шаг 3. Работать и делать коммиты

git add .
git commit -m "feat: add user profile"

Коммиты должны быть небольшими и логически связанными.

Шаг 4. Опубликовать feature

Если работа ведётся через remote:

git flow feature publish user-profile

или:

git push -u origin feature/user-profile

Шаг 5. Создать Pull Request

Из:

feature/user-profile

в:

develop

После ревью и успешного прохождения CI изменения можно вливать в develop.


4. Как вливать Feature в develop

Есть два допустимых варианта.

Вариант A — через Pull Request

Для командной разработки это предпочтительный способ:

feature/user-profile
        │
        │ Pull Request
        ↓
     develop

Плюсы:

  • code review;
  • автоматические проверки;
  • прозрачная история;
  • возможность обсуждать изменения до merge.

Вариант B — через git-flow локально

Можно использовать:

git flow feature finish user-profile

Эта команда завершает feature и вливает её в develop.

После этого изменения нужно отправить в remote:

git push origin develop

Если проект использует обязательный Pull Request, локальный feature finish обычно не используется для финального merge.


5. Важно: не все Feature должны зависеть друг от друга

Предпочтительная структура:

develop
 ├── feature/A
 ├── feature/B
 └── feature/C

Нежелательная структура:

develop
 └── feature/A
       └── feature/B
             └── feature/C

Каждая feature по возможности должна начинаться от develop.


6. Что делать, если Feature зависит от другой Feature

Иногда feature/B действительно требует незавершённых изменений из feature/A.

Например:

develop
   \
    feature/A
          \
           feature/B

В этом случае временно допустимо создать feature/B от feature/A.

Пример:

git checkout feature/A
git checkout -b feature/B

Но нужно понимать, что теперь B зависит от A.

После завершения A желательно вернуть B на обычную базу:

develop
   ├── feature/A
   └── feature/B

Например, после merge A в develop:

git checkout feature/B
git rebase develop

или выполнить merge:

git checkout feature/B
git merge develop

Выбор между rebase и merge зависит от правил проекта.

Главное правило:

Зависимая feature — временное исключение, а не стандартная структура проекта.

Подробнее о зависимостях см. GIT_BRANCH_DEPENDENCIES.ru.md.


7. Как обновлять Feature от develop

Пока feature разрабатывается, в develop могут появляться новые изменения.

Периодически feature необходимо синхронизировать.

Вариант с rebase

git checkout feature/user-profile
git fetch origin
git rebase origin/develop

Вариант с merge

git checkout feature/user-profile
git fetch origin
git merge origin/develop

Необходимо использовать тот вариант, который принят в правилах конкретного репозитория.

Если используется rebase для уже опубликованной ветки, после него может понадобиться:

git push --force-with-lease

Использовать:

git push --force

не рекомендуется.

Подробнее о безопасном использовании --force-with-lease см. в:

GIT_FORCE_WITH_LEASE_RECOVERY.ru.md


8. Release Flow

Когда набор изменений готов к релизу:

develop
   │
   └──→ release/2.4.0

Создание:

git flow release start 2.4.0

Далее выполняется:

  • финальное тестирование;
  • исправление найденных ошибок;
  • обновление версии;
  • подготовка release notes;
  • подготовка production-конфигурации.

Когда release готов:

release/2.4.0 → main
release/2.4.0 → develop

То есть результат релиза должен оказаться одновременно:

main

и

develop

Пример:

git flow release finish 2.4.0

После чего изменения необходимо отправить в remote:

git push origin main
git push origin develop
git push origin --tags

Конкретная последовательность зависит от используемого процесса CI/CD.


9. Почему release вливается и в main, и в develop

Предположим:

develop
   \
    release/2.4.0

Во время подготовки релиза нашли bug и исправили его в release.

Если отправить изменения только в main:

release → main

то исправление может не попасть обратно в будущую разработку.

Поэтому используется:

release → main
release → develop

Таким образом, develop не теряет исправления, сделанные во время подготовки релиза.


10. Hotfix Flow

Если production сломан и исправление требуется срочно:

main
  \
   hotfix/2.4.1

Создание:

git flow hotfix start 2.4.1

После исправления hotfix должен попасть:

hotfix/2.4.1 → main
hotfix/2.4.1 → develop

Пример:

git flow hotfix finish 2.4.1

После этого изменения публикуются:

git push origin main
git push origin develop
git push origin --tags

11. Bugfix Flow

Если ошибка обнаружена во время разработки и не требует отдельного production hotfix:

develop
   \
    bugfix/registration

Создание:

git flow bugfix start registration

После завершения:

bugfix/registration → develop

Использование bugfix или обычного feature для исправления ошибки определяется соглашениями проекта.

Главное — не создавать production hotfix от develop.


12. Support Flow

support/* нужен только тогда, когда проект действительно поддерживает старые версии.

Например:

main
 ├── 3.0
 └── support/2.x

Такие ветки позволяют поддерживать старую версию отдельно от основной разработки.

Использование support/* должно быть явно согласовано командой.

Если проект не требует поддержки нескольких версий одновременно, support лучше не использовать без необходимости.


13. Публикация веток

Для feature:

git flow feature publish <name>

Для остальных типов веток используются соответствующие publish/push команды согласно конфигурации git-flow.

Перед публикацией необходимо убедиться, что ветка имеет правильное имя и базовую ветку.

Проверить ветки можно:

git branch
git branch -r

Полезно также посмотреть историю:

git log --all --graph --decorate --oneline

Это один из самых удобных способов визуально проверить, куда действительно идут изменения.


14. От какого типа ветки что создаём

Ветка Создаётся от Основное назначение Куда вливается
feature/* develop Новая функциональность develop
bugfix/* develop Исправление ошибки в разработке develop
release/* develop Подготовка релиза main и develop
hotfix/* main Срочное production-исправление main и develop
support/* зависит от процесса Поддержка старой версии зависит от процесса

15. Что не следует делать

Не создавать Feature от main

Плохо:

main
  \
   feature/new-payment

Правильно:

develop
   \
    feature/new-payment

Не вливать Feature напрямую в main

Обычно:

feature → develop → release → main

а не:

feature → main

Не создавать Hotfix от develop

Плохо:

develop → hotfix

Правильно:

main → hotfix

Не держать Feature зависимой от другой Feature без необходимости

Плохо:

feature/A
    \
     feature/B
         \
          feature/C

Лучше:

develop
 ├── feature/A
 ├── feature/B
 └── feature/C

Не выполнять force push без необходимости

Опасно:

git push --force

Предпочтительно:

git push --force-with-lease

при условии, что force push разрешён правилами репозитория.


16. Рекомендуемый командный процесс

Для обычной задачи:

1. develop
      ↓
2. feature/*
      ↓
3. commits
      ↓
4. push
      ↓
5. Pull Request
      ↓
6. review + CI
      ↓
7. develop
      ↓
8. release/*
      ↓
9. main

В виде схемы:

                           Pull Request
feature/login ─────────────────────────→ develop
                                         │
                                         │ release
                                         ↓
                                      release/2.4.0
                                         │
                              ┌──────────┴──────────┐
                              ↓                     ↓
                            main                 develop

17. Правила Pull Request

Для командной работы рекомендуется:

  1. Один PR — одна логическая задача.
  2. Целевая ветка PR должна быть заранее определена.
  3. PR должен проходить CI до merge.
  4. Автор PR не должен самостоятельно обходить обязательные проверки.
  5. Конфликты необходимо разрешать в своей рабочей ветке, а не в develop/main.
  6. Не следует смешивать в одном PR feature, рефакторинг и несвязанные исправления.
  7. После изменения истории feature-ветки необходимо убедиться, что PR всё ещё содержит только нужные изменения.

Рекомендуемая схема:

feature/* → Pull Request → develop
release/* → Pull Request → main
hotfix/*  → Pull Request → main

Если политика проекта допускает отдельный merge release/hotfix в develop, это также должно быть явно зафиксировано в правилах репозитория.


18. Конвенция именования веток

Название ветки должно быть коротким и отражать задачу.

Примеры:

feature/user-profile
feature/payment-api
feature/checkout-flow

bugfix/registration-error
bugfix/incorrect-total

release/2.4.0

hotfix/2.4.1

support/2.x

Не рекомендуется:

feature/test
feature/new
feature/fix
feature/ivan
feature/123

Если в проекте используется трекер задач, предпочтительно включать идентификатор задачи:

feature/PROJ-123-user-profile
bugfix/PROJ-456-invalid-total

Точная схема именования должна быть одинаковой для всей команды.


19. Коммиты

Коммиты должны быть:

  • небольшими;
  • законченными;
  • логически связанными;
  • понятными без чтения всего diff.

Плохо:

git commit -m "fix"
git commit -m "changes"
git commit -m "test"

Лучше:

git commit -m "feat: add user profile endpoint"
git commit -m "fix: validate empty email"
git commit -m "test: cover invalid payment status"

Если проект использует Conventional Commits, придерживаемся его правил:

feat:
fix:
refactor:
test:
docs:
chore:
build:
ci:

20. Синхронизация перед началом работы

Перед созданием новой feature:

git fetch origin
git checkout develop
git pull --ff-only origin develop

После этого:

git flow feature start my-feature

Для hotfix:

git fetch origin
git checkout main
git pull --ff-only origin main
git flow hotfix start 2.4.1

Использование --ff-only помогает не создавать случайные локальные merge-коммиты во время обычного обновления базовой ветки.


21. Что делать при конфликтах

Если конфликт возник при rebase:

git status

Исправить конфликтующие файлы, затем:

git add <files>
git rebase --continue

Чтобы полностью отменить rebase:

git rebase --abort

Если конфликт возник при merge:

git status

После исправления:

git add <files>
git commit

Если merge необходимо отменить:

git merge --abort

Не следует разрешать конфликты вслепую. После разрешения обязательно проверить diff и тесты.


22. Удаление завершённых веток

После merge завершённая feature обычно больше не нужна.

Локальную ветку можно удалить:

git branch -d feature/my-feature

Удалённую ветку:

git push origin --delete feature/my-feature

Если репозиторий автоматически удаляет ветку после merge, вручную удалять её не нужно.

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


23. Как проверить поток коммитов

Для просмотра всех локальных и remote веток:

git log --all --graph --decorate --oneline --date-order

Полезно также:

git branch -a

и:

git show-branch --all

Пример графа:

*   abc1234 (main) Merge release/2.4.0
|\
| * def5678 (release/2.4.0) Prepare release 2.4.0
| * 123abcd Fix release configuration
|/
*   456efgh (develop) Merge feature/payment
|\
| * 789ijkl (feature/payment) Add payment service
| * 012mnop Add payment validation
|/
* 345qrst Previous release

Такой граф позволяет быстро проверить:

  • от какой ветки была создана ветка;
  • какие изменения в неё попали;
  • где находится merge;
  • не ушла ли feature в неправильную ветку.

24. Частые ошибки

Feature создана от старого develop

Симптом:

feature
   \
    старый develop

Решение — сначала синхронизировать feature с актуальным develop.


Feature случайно создана от main

Не продолжайте разработку, не проверив ситуацию.

Сначала нужно убедиться, какие изменения уже появились в feature, и только после этого выбрать способ переноса на актуальный develop.

В зависимости от ситуации это может быть:

git rebase develop

или пересоздание ветки от правильной базы.


В hotfix попали незавершённые изменения из develop

Это обычно означает, что hotfix создавался не от актуального main.

Hotfix должен базироваться на том состоянии, которое реально находится в production.


Исправление сделано только в release

Если release содержит важный bugfix, он должен попасть и в main, и обратно в develop.

Нельзя оставлять важные исправления только внутри временной release-ветки.


Два разработчика одновременно переписали историю одной feature

Не следует выполнять rebase/force push общей ветки без согласования.

Для опубликованных веток безопаснее:

git push --force-with-lease

Но даже --force-with-lease не отменяет необходимость договориться с остальными участниками.

Подробнее: GIT_FORCE_WITH_LEASE_RECOVERY.ru.md.


25. Полная схема Git Flow

                                      feature/A
                                     /
                                    /
                                   ●
                                  /
                                 /
develop ────────────────●────────●───────────────●────────
                         \                     /
                          \                   /
                           \                 /
                            release/2.4.0
                                   │
                          ┌────────┴────────┐
                          ↓                 ↓
                        main             develop
                          │
                          │
                          └── hotfix/2.4.1
                                  │
                         ┌────────┴────────┐
                         ↓                 ↓
                       main             develop

Для обычной разработки поток выглядит так:

develop
   │
   ├── feature/A ──────────────┐
   │                           ↓
   ├── feature/B ─────────→ develop
   │
   └── feature/C ──────────────┘
                                │
                                ↓
                           release/2.4.0
                                │
                          ┌─────┴─────┐
                          ↓           ↓
                        main       develop

26. Краткая памятка

Запоминаем:

feature ← develop
feature → develop

bugfix  ← develop
bugfix  → develop

release ← develop
release → main
release → develop

hotfix  ← main
hotfix  → main
hotfix  → develop

Основные команды:

# Feature
git flow feature start <name>
git flow feature publish <name>
git flow feature finish <name>

# Bugfix
git flow bugfix start <name>
git flow bugfix finish <name>

# Release
git flow release start <version>
git flow release finish <version>

# Hotfix
git flow hotfix start <version>
git flow hotfix finish <version>

# Support
git flow support start <name>

Для просмотра графа:

git log --all --graph --decorate --oneline --date-order

27. Наше командное правило

Перед каждой операцией с ветками нужно ответить на три вопроса:

1. От какой ветки я создаю текущую ветку?

2. В какую ветку должны попасть мои изменения?

3. Не содержит ли моя ветка изменений, которые не должны попасть в целевую ветку?

Если на эти три вопроса есть однозначный ответ, операция с Git почти всегда становится предсказуемой.


28. Итог

Нормальный Git Flow в команде выглядит так:

                         feature
                       ↗
develop ───────────────●───────────────
   │
   │ release
   ↓
 main
   │
   │ hotfix
   ↓
 develop

Ключевая идея проста:

develop — источник обычной разработки, main — источник production-правок. Feature идут в develop, release — в main и обратно в develop, hotfix — из main в main и обратно в develop.

Git Flow — это не набор обязательных магических команд. Это договорённость команды о том, где рождаются изменения, через какие этапы проходят и в какую ветку попадают.

Перед merge всегда проверяем целевую ветку, актуальность базы, CI и содержимое diff.