Git Merge Conflict: Пошаговое решение за 5 минут

Вы сделали git merge или git pull, и терминал выдал зловещее сообщение «CONFLICT (content): Merge conflict in…»? Не паникуйте. Конфликт слияния — это не ошибка и не поломка репозитория. Это штатная ситуация, когда Git не может автоматически объединить изменения из двух веток.

В этом руководстве мы разберём, как читать маркеры конфликтов,.resolve их вручную и через IDE, а также как предотвратить подобные ситуации в будущем.

Почему возникает merge conflict?

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

  • Вы и коллега отредактировали одну функцию параллельно
  • Вы изменили строку, которая была удалена в другой ветке
  • Два коммита модифицировали один и тот же блок кода по-разному

Важно: конфликт возникает только при слиянии (merge), ребейзе (rebase) или cherry-pick. Обычные коммиты никогда не вызывают конфликтов.

Шаг 1: Чтение маркеров конфликта

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

<<<<<<< HEAD
ваш текущий код (ветка, в которую сливаете)
=======
входящий код (ветка, которую сливаете)
>>>>>>> feature-branch

Что означает каждый маркер:

  • <<<<<<< HEAD — начало вашего текущего кода (ветка, на которой вы находитесь)
  • ======= — разделитель между двумя версиями
  • >>>>>>> feature-branch — конец входящего кода (ветка, которую вы сливаете)

Ваша задача — удалить все маркеры и оставить только правильный код. Иногда нужно сохранить обе версии, иногда — выбрать одну, иногда — написать новую.

Шаг 2: Разрешение конфликта вручную

Самый надёжный способ — открыть файл в любом текстовом редакторе и решить конфликт руками.

Пример разрешения:

Было (конфликт):

<<<<<<< HEAD
$timeout = 30;
=======
$timeout = 60;
>>>>>>> feature/update-timeout

Стало (после решения — выбираем большее значение):

$timeout = 60;

После редактирования сохраните файл и выполните:

# Помечаем конфликт как решённый
git add <имя_файла>

# Завершаем слияние
git commit -m "Resolve merge conflict in config.php"

Шаг 3: Разрешение через IDE (рекомендуемый способ)

Современные IDE показывают конфликты визуально и позволяют решать их кликами. Это быстрее и безопаснее ручного редактирования.

VS Code:

  • Откройте файл с конфликтом
  • Над каждым блоком появятся кнопки: Accept Current Change, Accept Incoming Change, Accept Both Changes, Compare Changes
  • Выберите нужный вариант одним кликом
  • Сохраните файл и сделайте коммит

PhpStorm / IntelliJ IDEA:

  • При конфликте появится диалог Conflicts
  • Нажмите Merge — откроется трёхпанельный инструмент
  • Левая панель — ваша версия, правая — входящая, центральная — результат
  • Переносите нужные блоки стрелками в центральную панель
  • Нажмите Apply

Шаг 4: Что делать, если всё пошло не так

Если вы запутались в конфликтах и хотите начать заново, можно безопасно отменить слияние:

# Полная отмена merge — возвращает состояние ДО команды git merge
git merge --abort

# Для rebase:
git rebase --abort

Эта команда работает только пока слияние не завершено (нет финального коммита). После коммита используйте git reset --hard HEAD~1, но будьте осторожны — это необратимо.

Лучшие практики предотвращения конфликтов

  • Сливайте основную ветку в свою регулярно (минимум раз в день)
  • Работайте над разными файлами, когда это возможно
  • Разбивайте большие задачи на мелкие PR/MR
  • Коммитьте часто — маленькие коммиты легче сливать
  • Общайтесь с командой перед изменением общих файлов
  • Используйте git pull --rebase вместо обычного pull для линейной истории

Что делать, если конфликты возникают постоянно?

Файл меняется слишком часто

Если один файл вызывает конфликты ежедневно — это архитектурный запах. Рассмотрите возможность разделения файла на модули, выделения конфигурации в отдельный файл или пересмотра ответственности компонентов.

Команда работает без координации

Частые конфликты — сигнал о проблемах в процессе. Внедрите code review, планирование спринтов и согласование зон ответственности. Технические средства не заменят коммуникацию.

Слишком длинные feature-ветки

Если ветка живёт недели без слияния с основной, конфликты неизбежны. Используйте trunk-based development или сокращайте цикл разработки до 1-3 дней.