Все главы учебника
Содержание учебника
Глава 05 / Git

Слияние и конфликт: собрать осмысленный результат

18 мин чтенияКонтент v0.10.0

Две правки одного правила

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

Merge объединяет другую линию с текущей веткой. Перед запуском проверьте имя через git branch --show-current. Если текущая вершина является предком другой линии, возможно быстрое продвижение, fast-forward: имя просто переместится вперёд. Когда линии разошлись, обычное слияние создаёт коммит с двумя родителями. Руководство merge описывает остановку, завершение и отмену операции.

Слияние не является копированием «всех файлов из topic поверх main». Git сопоставляет изменения относительно общего предка. Если одна ветка добавила README, а другая — отдельный файл settings, оба изменения могут объединиться автоматически. Даже отсутствие текстового конфликта не доказывает правильность программы: две совместимые строки могут создать несовместимое поведение.

Создайте конфликт в новой папке

lab=$(mktemp -d "${TMPDIR:-/tmp}/git-05.XXXXXX")
cd "$lab"
git init -b main
git config user.name "Учебный автор"
git config user.email "learner@example.invalid"
git config commit.gpgsign false
printf 'queue=16\n' > settings.txt
git add settings.txt
git commit -m "Set base capacity"
git switch -c topic
printf 'queue=32\n' > settings.txt
git add settings.txt
git commit -m "Try capacity 32"
git switch main
printf 'queue=8\n' > settings.txt
git add settings.txt
git commit -m "Try capacity 8"
git merge topic

Последняя команда должна остановиться с конфликтом. Не запускайте этот блок как скрипт, который считает любой ненулевой код неожиданной поломкой. Теперь посмотрите status и содержимое файла:

git status --short
cat settings.txt
git show :1:settings.txt
git show :2:settings.txt
git show :3:settings.txt

В status видно UU settings.txt. В файле — разделители <<<<<<<, =======, >>>>>>>. Для этого обычного merge первая конфликтующая часть соответствует main, вторая — topic. Команды show читают из индекса базу, текущую сторону и другую сторону соответственно: шестнадцать, восемь и тридцать два. Эти номера полезны, когда исходная строка в маркерах не показана.

Примите решение и завершите

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

printf 'queue=24\n' > settings.txt
git add settings.txt
git diff --cached
git commit -m "Merge capacity options with limit 24"
git log --graph --oneline --all
git rev-list --parents -n 1 HEAD

У последнего коммита должны быть два родителя. Рабочий файл не содержит маркеров. git add здесь сообщает, что вы выбрали результат для файла; он не проверяет смысл числа. Перед commit прогоните проверку проекта, если такая есть. Для нашего текста достаточно проверить одну строку и допустимое число; в финальном проекте будет shell-тест.

Если пока не готовы выбирать, git merge --abort отменяет незавершённое слияние. В учебной папке мы начинали с чистого дерева, поэтому возврат наблюдаем. С несохранёнными правками до merge отмена сложнее; в реальном проекте сначала защитите свою работу.

Проверьте смысл автоматического результата

Одна ветка меняет settings на очередь 32, другая отдельно пишет в README «очередь не превышает 16». Пути разные, поэтому Git может объединить их без остановки. Получится ли корректный проект? Нет: снимок содержит противоречивый договор. Добавьте такой пример в отдельной временной истории и прочитайте оба файла после merge. Он показывает, почему проверка только наличия маркеров недостаточна.

В своём разборе разделите два результата: Git сумел построить общий текст, а вы подтвердили согласованность правил. Первый проверяется завершением операции и состоянием индекса; второй — чтением требований и тестом проекта. Если проверяющий просит изменить решение конфликта, это обычная доработка содержания, а не доказательство неправильной работы механизма слияния. Назовите, какой файл и какое правило нужно проверить после вашего компромисса. Так вы сможете переносить этот опыт с учебной строки на настоящий код, не полагаясь только на зелёный статус операции.

Самостоятельная лаборатория

Практика — 35–50 минут. В новой истории создайте конфликт двух формулировок одной команды запуска. Сначала покажите общий вариант и две стороны. Не выбирайте сторону целиком только потому, что редактор предлагает кнопку: составьте итоговую инструкцию, которая содержит нужные сведения обеих правок.

Первый раз отмените слияние и убедитесь, что выбранная ветка осталась на прежнем коммите. Второй раз повторите merge, разрешите конфликт и создайте запись. Затем объедините две ветки, менявшие разные файлы, и сравните отсутствие конфликта с предыдущим опытом. При необходимости используйте --no-edit, чтобы принять автоматически созданное сообщение слияния без открытия редактора.

Критерии готовности

Вы знаете, в какую ветку попадёт результат, можете показать общего предка и две стороны, удалили маркеры и объяснили выбранное содержание. В завершённом случае status чист, последняя запись имеет двух родителей. В отменённом случае нового merge-коммита нет. Вы отделяете текстовую совместимость от правильности требований.

Разбор

Очередь двадцать четыре получилась потому, что это условие опыта. Число родителей подтверждает интеграцию линий, но не разумность компромисса. Если commit сохранил маркеры, Git может считать файл разрешённым после add — человеческая проверка была пропущена. Если merge прошёл fast-forward, значит текущая линия не имела своего независимого продолжения.

Дальше создадим локальный общий репозиторий. Первичный источник — git merge, особенно описание true merge и разрешения конфликтов. Сохраните свой рисунок графа и одно предложение о причине решения: эти артефакты пригодятся при будущем ревью.