Стратегии слияния: fast-forward, no-ff, squash
Три способа сделать git merge — и у каждого разная история коммитов в результате.
Fast-forward merge
Когда у main нет новых коммитов после того как ответвилась feature, Git просто перемещает указатель:
До:
main: A─B
\
feature: C─D─E
После fast-forward:
main: A─B─C─D─E
↑ просто переместили указатель
git switch main
git merge feature # fast-forward по умолчаниюИстория выглядит линейной — как будто feature и не было. Хорошо для небольших правок.
No-fast-forward (--no-ff)
Всегда создаёт merge-коммит, даже если возможен fast-forward:
После --no-ff:
main: A─B──────────M
\ ↑ merge-коммит
feature: C─D─E─╯
git merge feature --no-ffВ истории видно что была отдельная ветка. Удобно для аудита — сразу ясно что это была одна фича.
Squash merge
Сжимает все коммиты ветки в один:
После squash:
main: A─B─S
↑ один коммит со всеми изменениями feature
feature: A─B─C─D─E (остаётся без изменений)
git merge feature --squash
git commit -m "feat: полное описание фичи"Squash не создаёт merge-коммит автоматически — нужен явный git commit. Ветка feature при этом не удаляется и не сливается технически.
Попробуй в симуляции
Выбери стратегию и посмотри как изменится граф истории.
Сравнение
| Fast-forward | No-ff | Squash | |
|---|---|---|---|
| Merge-коммит | ✗ | ✓ | ✓ |
| История ветки | Не видна | Видна | Не видна |
| Количество коммитов | Все | Все + merge | Один |
| Читаемость | Линейная | Структурная | Чистая |
Когда что использовать
Fast-forward — мелкие правки, hotfix, один человек
No-ff — когда важно сохранить факт наличия ветки (feature ветки в GitFlow)
Squash — большие фичи с черновыми коммитами ("fix fix fix"), pull requests
Настройка по умолчанию
# Всегда no-ff для конкретного репозитория
git config merge.ff false
# Глобально
git config --global merge.ff falsegit merge feature