# Fast-forward merge _Ветки и слияния · GitLab Knowledge Base_ **TL;DR:** Простейшая форма merge: Git двигает указатель ветки на новый коммит без создания merge-объекта. Возможен, когда у целевой ветки нет коммитов после ветвления. Когда `git merge feat` выполняется на ветке `main`, Git сначала проверяет: можно ли просто «перемотать» main на верхушку feat? ## Когда возможен Когда main с момента ветвления не получала новых коммитов: ``` до merge: main: A → B \ feat: C → D git switch main && git merge feat: после: main: A → B → C → D ← main "догнал" feat feat: A → B → C → D ``` Никакого merge-коммита. Просто файл `.git/refs/heads/main` переписывается со старого SHA на SHA коммита D. ## Когда невозможен Когда на main был хотя бы один коммит после ветвления: ``` main: A → B → E \ feat: C → D ``` Здесь fast-forward невозможен, нужен three-way merge с merge-коммитом (см. [merge](/courses/git/kb/merge.md)). ## Контроль поведения ```bash git merge feat # ff если возможен, иначе three-way git merge --no-ff feat # всегда создаёт merge-коммит, # даже когда ff возможен git merge --ff-only feat # только ff; если невозможен - отказ ``` - `--no-ff` - стратегия команд, которые хотят сохранять топологию: «здесь была feature-ветка». Полезно для GitFlow. - `--ff-only` - страховка от случайных merge-коммитов. Удобно как дефолт для `pull`: `git config --global pull.ff only`. ## Подводные камни - Fast-forward не создаёт коммит, поэтому в `git log --oneline --graph` не видно, что была ветка. Если факт ветвления важен для аудита - `--no-ff`. - При `--ff-only` и расхождении веток Git откажется работать - нужно явно merge или rebase, не «как-нибудь автоматически». - У `pull` дефолт исторически другой; чтобы не получать случайные merge-коммиты - `pull.ff = only` или `pull.rebase = true`. ## Команды ```bash git merge feat ``` Слить feat в текущую; ff если возможен ```bash git merge --no-ff feat ``` Всегда создать merge-коммит, сохранить топологию ```bash git merge --ff-only feat ``` Только fast-forward; отказ при расхождении ## См. также - [git merge](/courses/git/kb/merge.md) - [git rebase](/courses/git/kb/rebase.md) - [Ветка (branch)](/courses/git/kb/branch.md)