Конфликты слияния
Конфликты слияния возникают, когда несколько авторов редактируют один и тот же контент или когда один разработчик удаляет файл, в то время как другой вносит в него изменения. Чтобы решить эту проблему, разработчики работают в изолированных ветках. Команда git merge отвечает за объединение изолированных веток и разрешение конфликтующих правок.
Git упрощает процесс слияния по сравнению с большинством систем контроля версий. Во многих случаях Git может автоматически интегрировать новые изменения. Однако в случае конфликтов Git не может автоматически определить, какая версия является правильной. Он помечает файл как конфликтующий и останавливает процесс слияния.

Распространённые прерывания слияния
Ошибки могут возникать в двух точках: в начале процесса слияния или во время него. Обратите внимание, что обычно они вызваны незафиксированными локальными изменениями, а не фактическими конфликтами содержимого.
Сбой слияния при запуске
Git не может начать слияние, потому что ожидающие изменения в рабочей директории или области индексации проекта будут перезаписаны коммитами, которые сливаются. Это происходит из-за ожидающих локальных изменений. Чтобы взять под контроль локальное состояние, используются команды git stash, git checkout, git commit и git reset. При возникновении ошибки на этапе запуска появится следующее сообщение:
конфликты git
error: Your local changes to the following files would be overwritten by merge:Сбой во время слияния
Сбой во время слияния указывает на наличие конфликта между текущей локальной веткой и веткой, которая сливается. При возникновении ошибки во время слияния появится следующее сообщение:
сбой во время слияния
CONFLICT (content): Merge conflict in example.txt
Automatic merge failed; fix conflicts and then commit the result.Создание конфликта слияния
Здесь мы покажем вам симуляцию того, как появляются конфликты слияния.
конфликты слияния
mkdir test-dir
cd test-dir
git init .
echo "some content" > example.txt
git add example.txt
git commit -m "initial commit"
[master (root-commit) a45c22d] initial commit
1 file changed, 1 insertion(+)
create mode 100644 example.txtВ приведённом примере мы создаём новую директорию с именем test-dir. Далее мы создаём текстовый файл example.txt с некоторым содержимым, добавляем его в репозиторий и делаем коммит. В результате у нас появляется новый репозиторий с одной мастер-веткой и файлом example.txt. Следующий шаг — создание другой ветки, которая будет использоваться для конфликтного слияния.
разрешение конфликтов
git checkout -b branch_to_merge
echo "completely different content to merge later" > example.txt
git commit -m "edit the content of example.txt to make a conflict"
[branch_to_merge 4221135] edit the content of example.txt to make a conflict
1 file changed, 1 insertion(+), 1 deletion(-)В приведённом выше примере мы создаём и переключаемся на ветку branch_to_merge. После её создания мы перезаписываем содержимое в example.txt и делаем коммит. После выполнения всех этих действий коммит перезаписывает содержимое example.txt:
конфликты слияния git
git checkout master
Switched to branch 'master'
echo "content to add" >> example.txt
git commit -m "added content to example.txt"
[master 11ab34b] added content to example.txt
1 file changed, 1 insertion(+)Эти команды переключают на мастер-ветку, добавляют содержимое в example.txt и фиксируют изменение. Это переводит репозиторий в состояние, в котором ветки master и branch_to_merge имеют уникальные коммиты. Последний шаг — выполнение команды git merge, после которой возникнет конфликт:
git merge
git merge branch_to_merge
Auto-merging example.txt
CONFLICT (content): Merge conflict in example.txt
Automatic merge failed; fix conflicts and then commit the result.Определение конфликтов слияния
Как мы уже видели, Git выводит сообщение, указывающее на появление конфликта. Выполните команду git status, чтобы увидеть неслитые пути:
конфликты git
git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: example.txtФайл example.txt отображается в изменённом состоянии. Выполните команду cat, чтобы отобразить содержимое файла example.txt. Мы можем увидеть следующие визуальные маркеры:
разрешение конфликтов git
<<<<<<< HEAD
=======
>>>>>>> branch_to_mergeМаркер ======= указывает на центр конфликта. Содержимое между маркерами <<<<<<< HEAD и ======= принадлежит текущей ветке (master), на которую указывает ссылка HEAD. Чтобы полностью отменить слияние и вернуться к состоянию до слияния, выполните git merge --abort. Подробнее о визуальных маркерах читайте на странице git merge.
Разрешение конфликтов слияния
Чтобы разрешить конфликт слияния, необходимо отредактировать конфликтующий файл. Откройте файл example.txt в редакторе, удалите маркеры конфликтов и сохраните нужные изменения. Разрешённый файл может выглядеть так:
конфликты в git
some content to mess with
content to addВыполните команду git add, чтобы добавить новое содержимое слияния в индекс. Далее создайте новый коммит, чтобы завершить слияние:
разрешение конфликтов в git
git add example.txt
git commit -m "the conflict in example.txt is merged and resolved"В качестве альтернативы вы можете использовать git mergetool для визуального разрешения конфликтов с помощью настроенного инструмента сравнения. Например, выполните git mergetool example.txt, чтобы открыть инструмент для конкретного файла.
| Инструмент | Описание |
|---|---|
git status | Помогает найти конфликтующие файлы. |
git mergetool | Открывает визуальный инструмент сравнения для интерактивного разрешения конфликтов. |
git diff | Показывает различия между коммитами, ветками или файлами, помогая выявить потенциальные конфликты до слияния. |
git checkout --ours/--theirs | Заменяет конфликтующий файл содержимым из текущей или входящей ветки. |
git reset --mixed | Отменяет добавление файлов в индекс, но оставляет рабочую директорию без изменений. |
git merge --abort | Отменяет текущее слияние и восстанавливает рабочую директорию в состояние до начала слияния. |
git reset | Сбрасывает индекс в соответствие с HEAD, помогая отменить добавление конфликтующих файлов. |
Практика
Какие аспекты обработки конфликтов слияния в Git существуют?