Конфликты в Git: разбор на живом проекте
Два разработчика меняют один блок конфигурации, и Git останавливает слияние вместо того, чтобы выбрать победителя. Разберём конфликт на примере проекта: как найти спорные строки, сохранить нужные изменения и проверить результат до коммита.

В проекте один разработчик меняет тайм-аут запроса, другой — адрес сервиса в том же файле. Git не может безопасно совместить правки и оставляет конфликт разработчику. На примере такого изменения разберём рабочий процесс для Git 2.43.0: от обнаружения конфликта до проверки и завершения слияния. Команды подходят и для актуальных версий Git 2.x, но детали интеграции могут зависеть от IDE и хостинга.
Сценарий: два изменения в одном файле
Представим конфигурационный файл, где в ветке main указан один адрес сервиса, а в ветке feature/timeout меняют тайм-аут. Между тем в main адрес уже обновили, причём в той же строке или рядом с ней. При слиянии Git видит пересекающиеся изменения и не может определить, какое итоговое значение задумано.
Это не ошибка репозитория и не потеря данных. Git прекращает операцию, помечает конфликтующие участки и ждёт, пока вы вручную сформируете итоговый вариант. Пока слияние не завершено, рабочая копия находится в промежуточном состоянии.
Git умеет показать, где изменения расходятся. Но решить, какое поведение нужно продукту, может только человек, который знает требования.
Сначала определите, что именно происходит
Конфликт может возникнуть при слиянии веток, при перебазировании или при попытке применить изменения из другого коммита. В этом примере используем обычный merge. До начала убедитесь, что рабочая копия не содержит несохранённых изменений, которые вы не хотите смешивать с операцией.
Проверьте состояние репозитория командой
git status. Если в выводе есть ваши незакоммиченные изменения, сначала сохраните их отдельным коммитом или временно отложите подходящим для вашего процесса способом. Проверка: вы понимаете, какие изменения относятся к текущей работе, а какие возникнут при слиянии.Перейдите в ветку, в которую нужно принять изменения, например
git switch main, и обновите её по принятому в команде процессу. Затем запуститеgit merge feature/timeout. Проверка: Git либо завершит слияние, либо сообщит о конфликтующих файлах.Снова выполните
git status. Git перечислит файлы, которые требуют разрешения. Проверка: вы знаете полный список конфликтующих путей, а не исправляете только первый файл, который попался на глаза.
Если команда сообщает, что слияние невозможно из-за локальных изменений, не удаляйте файлы и не запускайте очистку репозитория вслепую. Сначала выясните, какие именно изменения мешают: git status покажет их состояние.
Как читать конфликтные маркеры
Внутри конфликтующего файла Git обычно вставляет маркеры такого вида:
<<<<<<< HEAD
service_url = "https://service-new.example"
=======
service_url = "https://service.example"
>>>>>>> feature/timeout
В обычном merge часть между <<<<<<< HEAD и разделителем показывает вариант текущей ветки. Часть между ======= и завершающим маркером относится к вливаемой ветке. Имена могут быть разными: ориентируйтесь на конкретный вывод и контекст операции.
Маркеры — не команды и не часть итогового файла. Их нужно удалить вместе с ненужным вариантом и оставить корректный результат. В нашем условном проекте адрес из текущей ветки может быть актуальным, а тайм-аут из ветки с функцией нужно сохранить в соседней настройке. Но если конфликт возник в одной строке, объединить оба текста механически может быть нельзя: решайте по ожидаемому поведению приложения.
Сверьте не только строки вокруг маркера
Откройте файл целиком и сравните его с обеими версиями. В конфликте могли оказаться изменения, которые по отдельности выглядели безобидно, но вместе меняют смысл: например, адрес сервиса теперь указывает на другой контур, а тайм-аут выбран под старую задержку. Если контекст непонятен, спросите автора одной из веток или проверьте задачу, ради которой делали изменение.
Затем удалите все маркеры конфликта. Быстрая проверка поиском по файлам проекта помогает не оставить в исходниках строки, начинающиеся с <<<<<<<, ======= или >>>>>>>. Но одного поиска мало: маркеры могли быть удалены, а логика — остаться неправильной.
Отредактируйте, проверьте, завершите
Сформируйте содержимое файла так, как оно должно выглядеть после объединения. Не выбирайте целиком «свою» или «чужую» версию только потому, что так проще: можно потерять полезное изменение. Проверка: в файле нет маркеров, а нужные значения и структура на месте.
Посмотрите итоговые изменения командами
git diffиgit status. Git может пометить файл как разрешённый после его добавления в индекс, но это не подтверждает правильность содержимого. Проверка: diff показывает именно итоговую версию, которую вы собираетесь сохранить.Запустите тесты проекта и, если применимо, проверку конфигурации или сборку. Для конфигурационных файлов особенно полезно проверить приложение на тестовом окружении: синтаксически корректный файл всё равно может содержать неверный адрес или несовместимое значение. Проверка: необходимые проверки завершились успешно, а ожидаемое поведение воспроизводится.
Добавьте разрешённый файл командой
git add путь/к/файлу, указав реальный путь изgit status. Когда все конфликты решены, завершите merge коммитом: Git обычно подсказывает это в статусе и редакторе сообщения. Проверка: повторныйgit statusбольше не сообщает о неразрешённых конфликтах и показывает чистое состояние после коммита.
Что чаще всего ломается
Оставили маркер в файле. Сборка может упасть с синтаксической ошибкой или приложение прочитает некорректную конфигурацию. Найдите маркеры поиском по репозиторию и проверьте diff перед коммитом.
Выбрали одну сторону целиком. Так легко потерять изменение коллеги или собственную нужную правку. Сравните обе версии, а не нажимайте «Accept Current» или «Accept Incoming» автоматически.
Считаете, что статус «разрешено» означает «верно». Команда
git addотмечает файл как разрешённый для Git, но не проверяет смысл кода. Нужны тесты и осмысленный просмотр diff.Чините конфликт во время rebase по инструкции для merge. При перебазировании Git применяет коммиты по одному, а продолжение операции отличается. Посмотрите
git statusи следуйте его подсказкам; не запускайте команду продолжения merge наугад.Исправляете всё подряд после неудачного теста. Сначала отделите ошибки, связанные со слиянием, от уже существовавших проблем. Сравните результат с базовой веткой и попросите автора изменения помочь, если причина неясна.
Когда выбирать сторону, а когда объединять вручную
| Ситуация | Что делать | Цена решения |
|---|---|---|
| В одной ветке файл намеренно удалили, в другой изменили | Уточнить, действительно ли удаление входит в задачу; принять удаление или восстановить файл с изменениями | Неверный выбор может вернуть устаревший файл или убрать нужную функциональность |
| Обе ветки меняли разные настройки рядом | Собрать итог из обеих правок и проверить конфигурацию | Нужно понять взаимное влияние значений |
| Обе ветки меняли одну логику по-разному | Сверить требования и тесты, при необходимости привлечь авторов | Быстрого универсального выбора нет; цена ошибки — неправильное поведение приложения |
В IDE инструменты трёхстороннего сравнения показывают базовую версию и две изменённые. Это удобнее текстового редактора, если конфликт большой, но решение всё равно нужно проверить в контексте задачи. Не считайте вариант «слева» или «справа» правильным по умолчанию: расположение зависит от программы и операции.
Что делать дальше
После коммита проверьте изменения в той среде, где проявится их эффект: сборка, тестовый стенд, предпросмотр конфигурации или ревью коллеги. Если похожие конфликты повторяются в одном файле, договоритесь о владельце этого участка, разделите настройки по компонентам или синхронизируйте ветки раньше. Это не отменит конфликты, но уменьшит объём изменений, которые приходится разбирать за один раз.
Сноска. Конфликт слияния — ситуация, когда Git не может автоматически объединить изменения без риска выбрать неверный результат. Git помечает проблемное место, а разработчик задаёт итоговое содержимое.
Проверка рекламы на риски: Что в макете вызовет вопросы ФАС: превосходные степени, сравнения, обещания результата, маркировка.
Спросить за 40 ₽Источники: Git — Basic Branching and Merging, git merge — документация Git
Частые вопросы
Можно ли просто принять свою версию файла?
Что делать, если я случайно удалил нужные изменения при разрешении конфликта?
Почему Git считает конфликт решённым, хотя тесты не проходят?
Что делать, если конфликт возник при rebase?
Можно ли решить конфликт в веб-интерфейсе GitHub или GitLab?
Как понять, что после разрешения конфликта ничего не потеряно?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.