Слияние в Git: типичные ошибки и способы их исправить
Слияние веток в Git часто ломается не из-за сложного кода, а из-за неверной последовательности команд. Разбираем конфликты, fast-forward, потерянные изменения и проверку результата на Git 2.44+.

Слияние веток в Git обычно занимает одну команду, но ошибка в выбранной ветке или незаконченный конфликт могут оставить репозиторий в состоянии, где обычный git pull уже не помогает. Ниже — практические сценарии для Git 2.44 и новее: как выбрать режим merge, не потерять локальные изменения, разобрать конфликт и проверить результат до отправки в общий репозиторий.
Сначала проверьте, что именно вы сливаете
Большая часть ошибок начинается до команды git merge. Вы находитесь не в той ветке, не видите свежие коммиты с сервера или пытаетесь слить рабочие изменения, которые ещё не сохранены.
- Проверьте текущую ветку:
git branch --show-current. Результатом должна быть ветка, в которую вы хотите добавить изменения, напримерmain. - Посмотрите состояние рабочего дерева:
git status. Перед слиянием лучше иметь чистое состояние без незакоммиченных файлов. - Обновите сведения о ветках сервера:
git fetch origin. Эта команда скачивает новые указатели и коммиты, но не меняет файлы в рабочем каталоге. - Посмотрите последние коммиты:
git log --oneline --graph --decorate --all -n 20. Так вы увидите, действительно ли нужная ветка содержит изменения, которые нужно забрать.
Если перед слиянием у вас есть незавершённая работа, сохраните её отдельным коммитом или временно уберите через git stash. Не используйте stash как постоянное хранилище: забытые записи легко потерять среди других временных изменений.
Выберите режим слияния, а не принимайте случайный результат
Git может просто передвинуть указатель ветки, создать отдельный merge-коммит или отказаться от операции. Это разные результаты истории, и выбор влияет на ревью, откат и поиск причины сбоя.
| Команда | Результат | Когда выбирать | Цена решения |
|---|---|---|---|
git merge feature | Fast-forward, если ветка назначения не ушла вперёд; иначе Git создаст merge-коммит при необходимости | Когда политика проекта допускает стандартное поведение Git | Результат зависит от состояния истории и может быть неочевиден в ревью |
git merge --ff-only feature | Только перемещение указателя; при расхождении веток операция прекращается | Для линейной истории и автоматизированных проверок | Потребуется отдельно решить, как объединить расшедшиеся ветки |
git merge --no-ff feature | Всегда создаётся merge-коммит, даже если возможен fast-forward | Когда важно сохранить факт вливания отдельной функциональности | История становится более разветвлённой, а простой сценарий получает дополнительный коммит |
Fast-forward1 — это слияние без нового коммита: Git передвигает указатель ветки назначения на уже существующий коммит. Конфликта при таком перемещении быть не может, потому что Git не объединяет две изменившиеся линии истории.
Команда
git mergeне решает, какая версия кода «правильная». Она только объединяет историю. Решение о содержимом файлов остаётся за вами.
Ошибка 1. Слияние не той ветки
Типичный сценарий: разработчик хочет добавить feature/payment в main, но остаётся в feature-ветке и выполняет git merge main. В результате изменения из main попадают в feature-ветку, а нужное слияние так и не произошло.
git switch main
git fetch origin
git merge --ff-only origin/main
git merge --no-ff feature/payment
Первое переключение задаёт ветку назначения. Обновление от сервера нужно, чтобы не слить feature-ветку со старым локальным состоянием main. Если --ff-only завершился ошибкой, сначала разберитесь с расхождением веток, а не заменяйте его механически на --force: у git merge нет безопасного «принудительного» режима, который сам выберет правильную историю.
Ошибка 2. Незакоммиченные изменения блокируют merge
Git может остановить слияние сообщением вроде error: Your local changes to the following files would be overwritten by merge. Это защита от ситуации, в которой файлы из другой ветки затрут вашу незаписанную работу.
- Если изменения готовы — сохраните их:
git add ., затемgit commit -m "Save work before merge". - Если работа временная — используйте
git stash push -u -m "before merge", выполните слияние, а затем верните изменения черезgit stash pop. - Если изменения не нужны — удаляйте их только после проверки
git diffиgit status. Команды очистки рабочего дерева необратимы для незакоммиченных файлов.
Не создавайте коммит «на всякий случай», если в нём смешаны незавершённый код и подготовка к merge. Такой коммит усложнит ревью и может попасть в релиз вместе с экспериментальными изменениями.
Ошибка 3. Конфликт решён, но слияние не завершено
При конфликте Git оставляет репозиторий в состоянии merge in progress. В git status появится список конфликтующих файлов и подсказка выполнить git add после исправления. Простого сохранения файла недостаточно.
- Откройте каждый файл из списка
Unmerged paths. - Найдите маркеры
<<<<<<<,=======и>>>>>>>. Верхняя часть обычно относится к текущей ветке, нижняя — к сливаемой, но проверяйте подписи и контекст. - Оставьте корректный вариант или соберите новый из обеих частей. Удалите все маркеры.
- Проверьте diff:
git diff. Для уже добавленного в индекс файла используйтеgit diff --cached. - Отметьте файл решённым:
git add path/to/file. - Убедитесь, что конфликтов не осталось:
git status, затем завершите merge командойgit commitилиgit merge --continue, если Git предлагает именно её.
Проверка после конфликта обязательна. Запустите тесты проекта, сборку и хотя бы основные сценарии вручную. Git проверяет синтаксис истории, но не понимает, что изменение способно отправить деньги не тому получателю, скрыть кнопку оплаты или изменить формат API.
Ошибка 4. Принять «нашу» или «их» версию без проверки
Во время конфликта можно выбрать одну сторону, но это не всегда соответствует смыслу изменения. Команды git checkout --ours path/to/file и git checkout --theirs path/to/file применялись в старых и новых сценариях Git, однако их значение зависит от того, какая ветка считается текущей и какая сливается. В сложном конфликте механически выбирать одну сторону опасно.
Безопаснее открыть diff и принять решение по отдельным фрагментам. Для текстовых файлов можно использовать графический merge-инструмент, но после него всё равно проверьте git diff --cached. Для бинарных файлов автоматическое объединение обычно невозможно: понадобится выбрать один файл или восстановить содержимое из исходника.
Ошибка 5. После конфликта сразу отправить merge в origin
Команда git push origin main публикует не только техническое завершение merge, но и ваше решение о содержимом кода. Перед push проверьте:
git statusне показывает незавершённый merge;git log --oneline --graph -n 15содержит ожидаемый merge-коммит или линейное продолжение;git diff origin/main...HEADпоказывает именно набор изменений, который вы собирались отправить;- тесты и сборка проходят в том же окружении, где будет проверяться pull request;
- в коммит не попали файлы с секретами, локальными настройками и временными артефактами.
Если ветка на сервере изменилась после последнего fetch, push может завершиться сообщением rejected или non-fast-forward. Сначала скачайте изменения, изучите их и выполните согласованное с командой слияние. Не используйте git push --force для общей ветки: эта команда может переписать опубликованную историю.
Что делать, если merge пошёл не по плану
Нужно отменить незавершённое слияние
Пока Git сообщает о конфликте, обычно можно выполнить git merge --abort. Команда пытается вернуть состояние до начала merge. Незакоммиченные изменения, существовавшие до операции, могут восстановиться не полностью, поэтому перед сложным слиянием сохраняйте рабочие файлы отдельно.
Merge уже создан, но ещё не опубликован
Если merge-коммит — последний локальный коммит и после него вы ничего не публиковали, его можно отменить вместе с результатом операции командой git reset --hard HEAD^. Это удалит незакоммиченные изменения в рабочем каталоге, поэтому сначала сохраните нужные файлы и убедитесь, что переписывать локальную историю безопасно.
Merge уже попал в общую ветку
Для опубликованной истории безопаснее создать обратное изменение, а не переписывать ветку. Точная команда зависит от того, какой коммит и какую сторону слияния нужно отменить; перед git revert проверьте историю и согласуйте действие с владельцами репозитория.
Когда выбирать merge, а когда остановиться
Используйте --ff-only, если проект требует линейной истории и расхождение веток должно считаться ошибкой процесса. Выбирайте --no-ff, если команде важно видеть границы функциональных веток и откатывать их целиком. Обычный git merge подходит для проекта без жёсткой политики истории, но результат нужно проверять по графу коммитов.
Rebase — отдельный способ переписать основу коммитов, а не разновидность решения конфликта через merge. Не смешивайте его с этой процедурой в середине командной работы: порядок действий и риски для опубликованных веток будут другими.
Что делать дальше
Зафиксируйте в документации проекта один допустимый сценарий: какая ветка является основной, разрешён ли merge-коммит, обязательны ли тесты перед push и кто принимает решение по конфликтам. В CI добавьте проверку сборки и тестов для pull request, а локально привыкните начинать с git status и заканчивать просмотром графа истории. После следующего слияния измерьте не только время команды, но и количество исправлений, которые пришлось делать уже после публикации.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: Официальная документация Git: git-merge, Официальная книга Pro Git: ветвление и слияние
Частые вопросы
Можно ли отменить merge, если я уже начал решать конфликт?
Почему Git пишет non-fast-forward?
Что делать, если после решения конфликта Git всё ещё показывает unmerged paths?
Нужно ли всегда использовать git merge --no-ff?
Что изменится в другой версии Git?
Опасно ли использовать git push --force после неудачного merge?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.