Files
aston-team-project/tutorials/git/GIT_FLOW.ru.md
T

1202 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Git Flow: правила разработки в команде
## Назначение
Этот документ описывает принятый в команде порядок работы с Git Flow:
- какие ветки используются;
- от каких веток создавать новые;
- куда вливать изменения;
- как работать с `feature`, `release`, `hotfix`;
- как работать с зависимыми feature;
- как синхронизировать локальные ветки;
- как безопасно публиковать изменения;
- что делать через Pull Request.
Цель — сделать историю изменений предсказуемой и избежать ситуаций, когда изменения случайно попадают не в ту ветку.
---
## 1. Основная модель веток
В классическом Git Flow используются две основные долгоживущие ветки:
- `main` — код, находящийся в production;
- `develop` — основная ветка текущей разработки.
Временные ветки:
- `feature/*` — разработка новой функциональности;
- `release/*` — подготовка релиза;
- `hotfix/*` — срочное исправление production;
- `bugfix/*` — исправление ошибок в процессе разработки;
- `support/*` — поддержка старых версий, если это необходимо проекту.
Базовая схема:
```text
feature/*
/ \
/ \
/ \
main ─────────────────●──────────────●─────────────
↑ ↑
│ │
release hotfix
│ │
└──────┐ ┌─────┘
↓ ↓
develop ────────────────●────●─●──────────────────
↑
│
feature
```
Главное правило:
```text
feature/* → develop
release/* → main
release/* → develop
hotfix/* → main
hotfix/* → develop
```
---
# 2. Что является источником для каждой ветки
## Feature
Feature создаётся от:
```text
develop → feature/*
```
Пример:
```bash
git flow feature start user-profile
```
Получается:
```text
develop
\
feature/user-profile
```
Новые feature по умолчанию **не создаются от `main`**.
---
## Release
Release создаётся от:
```text
develop → release/*
```
Пример:
```bash
git flow release start 2.4.0
```
Получается:
```text
develop
\
release/2.4.0
```
Release используется для подготовки уже готового набора изменений к production.
В release обычно не добавляют новые большие функциональные возможности.
---
## Hotfix
Hotfix создаётся от:
```text
main → hotfix/*
```
Пример:
```bash
git flow hotfix start 2.4.1
```
Используйте `hotfix`, когда проблема уже находится в production и исправление нельзя ждать до следующего обычного релиза.
---
## Bugfix
`bugfix` используется для исправления ошибок в процессе разработки.
В зависимости от конфигурации `git-flow` такая ветка обычно является веткой разработки и должна в конечном итоге попасть в `develop`.
Пример:
```bash
git flow bugfix start fix-registration
```
---
# 3. Основной рабочий цикл Feature
Обычная разработка выглядит так:
```text
develop
│
├── feature/login
│
├── feature/payment
│
└── feature/profile
│
└────────→ develop
```
## Шаг 1. Обновить develop
Перед началом работы необходимо синхронизировать локальный `develop`:
```bash
git checkout develop
git pull origin develop
```
## Шаг 2. Создать feature
```bash
git flow feature start user-profile
```
## Шаг 3. Работать и делать коммиты
```bash
git add .
git commit -m "feat: add user profile"
```
Коммиты должны быть небольшими и логически связанными.
## Шаг 4. Опубликовать feature
Если работа ведётся через remote:
```bash
git flow feature publish user-profile
```
или:
```bash
git push -u origin feature/user-profile
```
## Шаг 5. Создать Pull Request
Из:
```text
feature/user-profile
```
в:
```text
develop
```
После ревью и успешного прохождения CI изменения можно вливать в `develop`.
---
# 4. Как вливать Feature в develop
Есть два допустимых варианта.
## Вариант A — через Pull Request
Для командной разработки это предпочтительный способ:
```text
feature/user-profile
│
│ Pull Request
↓
develop
```
Плюсы:
- code review;
- автоматические проверки;
- прозрачная история;
- возможность обсуждать изменения до merge.
---
## Вариант B — через git-flow локально
Можно использовать:
```bash
git flow feature finish user-profile
```
Эта команда завершает feature и вливает её в `develop`.
После этого изменения нужно отправить в remote:
```bash
git push origin develop
```
Если проект использует обязательный Pull Request, локальный `feature finish` обычно не используется для финального merge.
---
# 5. Важно: не все Feature должны зависеть друг от друга
Предпочтительная структура:
```text
develop
├── feature/A
├── feature/B
└── feature/C
```
Нежелательная структура:
```text
develop
└── feature/A
└── feature/B
└── feature/C
```
Каждая feature по возможности должна начинаться от `develop`.
---
# 6. Что делать, если Feature зависит от другой Feature
Иногда `feature/B` действительно требует незавершённых изменений из `feature/A`.
Например:
```text
develop
\
feature/A
\
feature/B
```
В этом случае временно допустимо создать `feature/B` от `feature/A`.
Пример:
```bash
git checkout feature/A
git checkout -b feature/B
```
Но нужно понимать, что теперь B зависит от A.
После завершения A желательно вернуть B на обычную базу:
```text
develop
├── feature/A
└── feature/B
```
Например, после merge A в `develop`:
```bash
git checkout feature/B
git rebase develop
```
или выполнить merge:
```bash
git checkout feature/B
git merge develop
```
Выбор между `rebase` и `merge` зависит от правил проекта.
Главное правило:
> Зависимая feature — временное исключение, а не стандартная структура проекта.
Подробнее о зависимостях см. `GIT_BRANCH_DEPENDENCIES.ru.md`.
---
# 7. Как обновлять Feature от develop
Пока feature разрабатывается, в `develop` могут появляться новые изменения.
Периодически feature необходимо синхронизировать.
### Вариант с rebase
```bash
git checkout feature/user-profile
git fetch origin
git rebase origin/develop
```
### Вариант с merge
```bash
git checkout feature/user-profile
git fetch origin
git merge origin/develop
```
Необходимо использовать тот вариант, который принят в правилах конкретного репозитория.
Если используется `rebase` для уже опубликованной ветки, после него может понадобиться:
```bash
git push --force-with-lease
```
Использовать:
```bash
git push --force
```
не рекомендуется.
Подробнее о безопасном использовании `--force-with-lease` см. в:
`GIT_FORCE_WITH_LEASE_RECOVERY.ru.md`
---
# 8. Release Flow
Когда набор изменений готов к релизу:
```text
develop
│
└──→ release/2.4.0
```
Создание:
```bash
git flow release start 2.4.0
```
Далее выполняется:
- финальное тестирование;
- исправление найденных ошибок;
- обновление версии;
- подготовка release notes;
- подготовка production-конфигурации.
Когда release готов:
```text
release/2.4.0 → main
release/2.4.0 → develop
```
То есть результат релиза должен оказаться одновременно:
```text
main
```
и
```text
develop
```
Пример:
```bash
git flow release finish 2.4.0
```
После чего изменения необходимо отправить в remote:
```bash
git push origin main
git push origin develop
git push origin --tags
```
Конкретная последовательность зависит от используемого процесса CI/CD.
---
# 9. Почему release вливается и в main, и в develop
Предположим:
```text
develop
\
release/2.4.0
```
Во время подготовки релиза нашли bug и исправили его в release.
Если отправить изменения только в `main`:
```text
release → main
```
то исправление может не попасть обратно в будущую разработку.
Поэтому используется:
```text
release → main
release → develop
```
Таким образом, `develop` не теряет исправления, сделанные во время подготовки релиза.
---
# 10. Hotfix Flow
Если production сломан и исправление требуется срочно:
```text
main
\
hotfix/2.4.1
```
Создание:
```bash
git flow hotfix start 2.4.1
```
После исправления hotfix должен попасть:
```text
hotfix/2.4.1 → main
hotfix/2.4.1 → develop
```
Пример:
```bash
git flow hotfix finish 2.4.1
```
После этого изменения публикуются:
```bash
git push origin main
git push origin develop
git push origin --tags
```
---
# 11. Bugfix Flow
Если ошибка обнаружена во время разработки и не требует отдельного production hotfix:
```text
develop
\
bugfix/registration
```
Создание:
```bash
git flow bugfix start registration
```
После завершения:
```text
bugfix/registration → develop
```
Использование `bugfix` или обычного `feature` для исправления ошибки определяется соглашениями проекта.
Главное — не создавать production hotfix от `develop`.
---
# 12. Support Flow
`support/*` нужен только тогда, когда проект действительно поддерживает старые версии.
Например:
```text
main
├── 3.0
└── support/2.x
```
Такие ветки позволяют поддерживать старую версию отдельно от основной разработки.
Использование `support/*` должно быть явно согласовано командой.
Если проект не требует поддержки нескольких версий одновременно, `support` лучше не использовать без необходимости.
---
# 13. Публикация веток
Для feature:
```bash
git flow feature publish <name>
```
Для остальных типов веток используются соответствующие `publish`/`push` команды согласно конфигурации `git-flow`.
Перед публикацией необходимо убедиться, что ветка имеет правильное имя и базовую ветку.
Проверить ветки можно:
```bash
git branch
git branch -r
```
Полезно также посмотреть историю:
```bash
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
Плохо:
```text
main
\
feature/new-payment
```
Правильно:
```text
develop
\
feature/new-payment
```
---
## Не вливать Feature напрямую в main
Обычно:
```text
feature → develop → release → main
```
а не:
```text
feature → main
```
---
## Не создавать Hotfix от develop
Плохо:
```text
develop → hotfix
```
Правильно:
```text
main → hotfix
```
---
## Не держать Feature зависимой от другой Feature без необходимости
Плохо:
```text
feature/A
\
feature/B
\
feature/C
```
Лучше:
```text
develop
├── feature/A
├── feature/B
└── feature/C
```
---
## Не выполнять force push без необходимости
Опасно:
```bash
git push --force
```
Предпочтительно:
```bash
git push --force-with-lease
```
при условии, что force push разрешён правилами репозитория.
---
# 16. Рекомендуемый командный процесс
Для обычной задачи:
```text
1. develop
↓
2. feature/*
↓
3. commits
↓
4. push
↓
5. Pull Request
↓
6. review + CI
↓
7. develop
↓
8. release/*
↓
9. main
```
В виде схемы:
```text
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 всё ещё содержит только нужные изменения.
Рекомендуемая схема:
```text
feature/* → Pull Request → develop
release/* → Pull Request → main
hotfix/* → Pull Request → main
```
Если политика проекта допускает отдельный merge release/hotfix в `develop`, это также должно быть явно зафиксировано в правилах репозитория.
---
# 18. Конвенция именования веток
Название ветки должно быть коротким и отражать задачу.
Примеры:
```text
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
```
Не рекомендуется:
```text
feature/test
feature/new
feature/fix
feature/ivan
feature/123
```
Если в проекте используется трекер задач, предпочтительно включать идентификатор задачи:
```text
feature/PROJ-123-user-profile
bugfix/PROJ-456-invalid-total
```
Точная схема именования должна быть одинаковой для всей команды.
---
# 19. Коммиты
Коммиты должны быть:
- небольшими;
- законченными;
- логически связанными;
- понятными без чтения всего diff.
Плохо:
```bash
git commit -m "fix"
git commit -m "changes"
git commit -m "test"
```
Лучше:
```bash
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, придерживаемся его правил:
```text
feat:
fix:
refactor:
test:
docs:
chore:
build:
ci:
```
---
# 20. Синхронизация перед началом работы
Перед созданием новой feature:
```bash
git fetch origin
git checkout develop
git pull --ff-only origin develop
```
После этого:
```bash
git flow feature start my-feature
```
Для `hotfix`:
```bash
git fetch origin
git checkout main
git pull --ff-only origin main
git flow hotfix start 2.4.1
```
Использование `--ff-only` помогает не создавать случайные локальные merge-коммиты во время обычного обновления базовой ветки.
---
# 21. Что делать при конфликтах
Если конфликт возник при `rebase`:
```bash
git status
```
Исправить конфликтующие файлы, затем:
```bash
git add <files>
git rebase --continue
```
Чтобы полностью отменить rebase:
```bash
git rebase --abort
```
Если конфликт возник при merge:
```bash
git status
```
После исправления:
```bash
git add <files>
git commit
```
Если merge необходимо отменить:
```bash
git merge --abort
```
Не следует разрешать конфликты вслепую. После разрешения обязательно проверить diff и тесты.
---
# 22. Удаление завершённых веток
После merge завершённая feature обычно больше не нужна.
Локальную ветку можно удалить:
```bash
git branch -d feature/my-feature
```
Удалённую ветку:
```bash
git push origin --delete feature/my-feature
```
Если репозиторий автоматически удаляет ветку после merge, вручную удалять её не нужно.
Не удаляйте ветку до тех пор, пока не убедились, что нужные изменения действительно попали в целевую ветку.
---
# 23. Как проверить поток коммитов
Для просмотра всех локальных и remote веток:
```bash
git log --all --graph --decorate --oneline --date-order
```
Полезно также:
```bash
git branch -a
```
и:
```bash
git show-branch --all
```
Пример графа:
```text
* 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
Симптом:
```text
feature
\
старый develop
```
Решение — сначала синхронизировать feature с актуальным `develop`.
---
## Feature случайно создана от main
Не продолжайте разработку, не проверив ситуацию.
Сначала нужно убедиться, какие изменения уже появились в feature, и только после этого выбрать способ переноса на актуальный `develop`.
В зависимости от ситуации это может быть:
```bash
git rebase develop
```
или пересоздание ветки от правильной базы.
---
## В hotfix попали незавершённые изменения из develop
Это обычно означает, что hotfix создавался не от актуального `main`.
Hotfix должен базироваться на том состоянии, которое реально находится в production.
---
## Исправление сделано только в release
Если release содержит важный bugfix, он должен попасть и в `main`, и обратно в `develop`.
Нельзя оставлять важные исправления только внутри временной release-ветки.
---
## Два разработчика одновременно переписали историю одной feature
Не следует выполнять `rebase`/force push общей ветки без согласования.
Для опубликованных веток безопаснее:
```bash
git push --force-with-lease
```
Но даже `--force-with-lease` не отменяет необходимость договориться с остальными участниками.
Подробнее: `GIT_FORCE_WITH_LEASE_RECOVERY.ru.md`.
---
# 25. Полная схема Git Flow
```text
feature/A
/
/
●
/
/
develop ────────────────●────────●───────────────●────────
\ /
\ /
\ /
release/2.4.0
│
┌────────┴────────┐
↓ ↓
main develop
│
│
└── hotfix/2.4.1
│
┌────────┴────────┐
↓ ↓
main develop
```
Для обычной разработки поток выглядит так:
```text
develop
│
├── feature/A ──────────────┐
│ ↓
├── feature/B ─────────→ develop
│
└── feature/C ──────────────┘
│
↓
release/2.4.0
│
┌─────┴─────┐
↓ ↓
main develop
```
---
# 26. Краткая памятка
Запоминаем:
```text
feature ← develop
feature → develop
bugfix ← develop
bugfix → develop
release ← develop
release → main
release → develop
hotfix ← main
hotfix → main
hotfix → develop
```
Основные команды:
```bash
# 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>
```
Для просмотра графа:
```bash
git log --all --graph --decorate --oneline --date-order
```
---
# 27. Наше командное правило
Перед каждой операцией с ветками нужно ответить на три вопроса:
**1. От какой ветки я создаю текущую ветку?**
**2. В какую ветку должны попасть мои изменения?**
**3. Не содержит ли моя ветка изменений, которые не должны попасть в целевую ветку?**
Если на эти три вопроса есть однозначный ответ, операция с Git почти всегда становится предсказуемой.
---
# 28. Итог
Нормальный Git Flow в команде выглядит так:
```text
feature
↗
develop ───────────────●───────────────
│
│ release
↓
main
│
│ hotfix
↓
develop
```
Ключевая идея проста:
> `develop` — источник обычной разработки, `main` — источник production-правок. Feature идут в `develop`, release — в `main` и обратно в `develop`, hotfix — из `main` в `main` и обратно в `develop`.
Git Flow — это не набор обязательных магических команд. Это договорённость команды о том, **где рождаются изменения, через какие этапы проходят и в какую ветку попадают**.
Перед merge всегда проверяем целевую ветку, актуальность базы, CI и содержимое diff.