Краткий ответ
Конфликт слияния Git возникает, когда две ветки изменяют одну и ту же часть файла. Решается так: откройте файлы с маркерами конфликта, вручную выберите или объедините изменения, сохраните, выполните `git add` и завершите с помощью `git commit` или `git merge --continue`. Если запутались, `git merge --abort` вернёт всё в состояние до слияния.
Как проявляется проблема
- Сообщение `CONFLICT (content): Merge conflict in ...` в терминале
- Файлы содержат маркеры `<<<<<<<`, `=======`, `>>>>>>>`
- `git status` показывает файлы в разделе "Unmerged paths"
- Слияние начато, но не завершено, `git log` не показывает новый коммит
- Редактор или IDE показывает красные маркеры на строках с конфликтом
Частые причины
Изменения одной и той же части файла в двух ветках
Две ветки изменяли одни и те же строки кода или один и тот же блок текста, поэтому Git не может автоматически решить, какая версия правильная.
Удаление или перемещение файла в одной ветке
Если файл удалён в одной ветке, а изменён в другой, Git сообщает о конфликте modify/delete.
Одновременная работа над одной веткой
Два разработчика изменяли один и тот же файл без получения последних изменений, поэтому слияние позже обнаруживает пересечение.
Настраиваемые параметры слияния
`.gitattributes` или пользовательские драйверы слияния могут влиять на то, как Git обрабатывает изменения и когда сообщает о конфликте.
Пошаговое решение
- 1
Проверьте состояние репозитория
Выполните
git status. Файлы с конфликтом будут перечислены в разделе "Unmerged paths". Запишите их или откройте терминал в корне проекта. Не прерывайте слияние, пока не решите, что хотите сделать. - 2
Откройте файл с конфликтом
Откройте каждый файл из списка в редакторе. Найдите маркеры
<<<<<<< HEAD,=======и>>>>>>> имя-ветки. При стиле по умолчанию часть между<<<<<<<и=======это ваша текущая ветка, а часть между=======и>>>>>>>приходит из сливаемой ветки. Если вы используете стильdiff3, есть также часть с общим предком между|||||||и=======. - 3
Вручную объедините изменения
Удалите все маркеры конфликта и оставьте только нужный код. Можно сохранить одну сторону, другую или объединить обе. Обратите внимание на скобки, запятые и отступы. Если не уверены, откройте историю файла (
git log -- файл), чтобы увидеть, кто что менял. - 4
Используйте редактор или IDE для просмотра
VS Code предлагает опции "Accept Current Change", "Accept Incoming Change" и "Accept Both Changes"; аналогичные опции есть и в других редакторах. Это быстрее, но всегда проверяйте результат. Не принимайте слепо обе стороны, если логика кода пересекается.
- 5
Сохраните и отметьте как решённое
Когда закончите с файлом, сохраните его и выполните
git add имя-файла. Повторите для всех файлов из списка.git statusтеперь должен показать "All conflicts fixed but you are still merging". - 6
Завершите слияние
Выполните
git commit(без-m, если хотите отредактировать сообщение) илиgit merge --continue. Этим создаётся коммит слияния. Проверьтеgit log --oneline -3, чтобы увидеть, что слияние зафиксировано. - 7
Протестируйте перед push
Запустите сборку и тесты (
npm test,mvn testили что использует проект). Конфликт может скрыть ошибку, которая проявится только при выполнении. Только когда тесты пройдут, выполнитеgit push. - 8
Если хотите отменить
Команда
git merge --abortвозвращает рабочий каталог в состояние до начала слияния. Используйте её, если решите, что лучше сначала получить изменения или посоветоваться с коллегой. Не используйтеgit reset --hard, если у вас есть несохранённые изменения.
Когда конфликт становится слишком большим
Если в файле десятки конфликтных блоков или вы не понимаете код, не выбирайте стороны наугад. Если хотите сохранить состояние перед слиянием, создайте резервную ветку до начала слияния (git branch моя-резервная); она не сохраняет несохранённые изменения в рабочем каталоге. Если начинаете слияние заново, на целевой ветке можно использовать git merge --no-commit, чтобы просмотреть изменения перед коммитом. Для больших конфликтов полезно включить git config merge.conflictstyle diff3, который показывает и общего предка, что облегчает понимание. Если конфликт включает бинарные файлы, Git не может их объединить; тогда нужно вручную выбрать одну версию (git checkout --ours файл или --theirs), затем выполнить git add файл.
Как избежать повторения
- Часто получайте изменения из главной ветки (`git pull --rebase`) перед началом крупной работы.
- Держите изменения небольшими и сфокусированными на одной задаче; коммитьте чаще.
- Договоритесь в команде, кто меняет какие файлы и части кода.
- Включите `git config merge.conflictstyle diff3`, чтобы легче понимать конфликты.
Когда лучше обратиться к специалисту
Если конфликт включает десятки файлов, бинарные файлы или вы не понимаете код достаточно, чтобы безопасно объединить изменения, обратитесь в IT поддержку или к более опытному коллеге, чтобы вместе разрешить конфликт и сохранить историю.
Разработка ПО и продуктов · Приложения на заказ, SaaS и MVP за 4-8 недельЧастые вопросы
Что означают маркеры `<<<<<<<`, `=======` и `>>>>>>>`?
`<<<<<<< HEAD` обозначает начало вашей текущей ветки, `=======` разделяет две версии, а `>>>>>>> имя-ветки` обозначает конец части из сливаемой ветки. Все маркеры конфликта должны быть удалены, прежде чем вы отметите файл как решённый.
Могу ли я отменить слияние, если уже выполнил `git add`?
Да, `git merge --abort` работает, пока вы не завершили коммит слияния. Если вы уже создали коммит слияния и не отправили его в удалённый репозиторий, можете отменить его с помощью `git reset --hard HEAD~1`, но сначала создайте резервную ветку или копию репозитория. Если коммит уже отправлен, используйте `git revert -m 1 <hash>`.
Как разрешить конфликт в бинарном файле?
Git не может автоматически объединить бинарные файлы. Решите, какая версия правильная, и выполните `git checkout --ours файл` (ваша ветка) или `git checkout --theirs файл` (другая ветка), затем `git add файл`.