Слияние веток
Ветку в которую мы хотим слить изменения, будем называть основной
, а ветку из которой мы будем их сливать тематической
. Существует две основных стратегии слияния:
- Явное слияние
- Неявное слияние
Явное слияние
Во время явного слияния создается так называемый merge-коммит
. Основное предназначение этого коммита состоит в том, чтобы соединить изменения двух веток. У этого коммита есть одна особенность: два родительских коммита. Один родитель – последний коммит сливаемой ветки, второй – последний коммит целевой ветки:
git merge --no-ff тематическая_ветка
Неявное слияние
Во время неявного слияния не создается новых коммитов: используются только уже существующие. Суть этого слияния заключается в том, что из вливаемой ветки извлекаются несколько коммитов, а затем они применяются к последнему коммиту целевой ветки. Такое слияние называется fast-forward
:
git merge тематическая_ветка
Прервать не зафиксированое слияние
Если слияние еще не зафиксировано, для прирывания используйте:
git merge --abort
Откатить зафиксированое слияние
Слияние собственно это, слияние данных из двух веток которые пошли независимыми путями. Если вы хотите отменить слияние, то логично что вы хотите отменить изменение одной из веток которые зафиксированны коммитом, тогда вам нужно сделать следующее:
git revert хеш_коммита_который_хотите_отменить -m 1
Тестовое слияние
Если нужно проверить возможность слияния веток на конфликты, есть специальная методика. Предположим, вы находитесь в master
ветке и хотели бы проверить, можно ли dev
ветку объединить без конфликта в master
, выполните команду:
git merge dev --no-ff --no-commit
Чтобы вернуться к нормальному состоянию, просто нужно прервать слияние:
git merge --abort
Ручное разрешение конфликта
Если обе ветви меняют одну и ту же часть файла, то возникает конфликт слияния. Ситуация в которой Git не знает, какую версию файла сохранить, поэтому разрешать конфликт нужно собственноручно. Для разрешения конфликта в любом текстовом редакторе откройте конфликтный файл, если файлов несколько, конфликт нужно устранять в каждом.
После открытия таких файлов вы увидите похожие маркеры разрешения конфликта:
<<<<<<< HEAD:index.html
Все, что находится выше =======, является версией в master ветке
=======
Все, что находится ниже =======, является версией в другой ветке
>>>>>>> test:index.html
Текст между <<<<<<< HEAD:index.html
и =======
, конфликтующее содержимое файла, на который указывает HEAD
, то есть файла из целевой ветки.
Все, что находится между =======
и >>>>>>> test:index.html
, содержимое файла из ветки test
.
Наша задача – объяснить Git, каким мы хотим видеть файл, для этого нам нужно вручную отредактировать файл. Не обязательно выбирать один из двух приведенных вариантов – в этом вся прелесть ручного редактирования. Мы можем удалить вообще весь текст из файла, оставить часть первого файла и часть второго или вообще написать что-то свое. Не забудьте удалить строки, которые оставил Git.
Добавляем в индекс измененный файл:
git add имя_файла
Создать новый коммит:
git commit -m "название_комита"
Подробный вывод
База слияния – это общий файл в котором будут показаны различия, именно база слияния является для нас самым важным состоянием при разрешении конфликта. Детальный просмотр поможет в понимании, какой из файлов нужно оставить.
Показать в конфликтном файле сравнение содержимого сливаемых веток плюс то, что было в месте конфликта в коммите на котором разошлись сливаемые ветки:
git checkout --conflict=diff3 --merge название_файла
Все, что находится между ||||||| 8b5b982
и =======
и есть наша база слияния. Иначе говоря, это содержимое файла из общего родителя двух последних коммитов в разных ветках. Число в строке 8b5b982
это хэш этого родителя, так что при необходимости можно посмотреть на него в логе репозитория.
<<<<<<< HEAD:index.html
Все, что находится выше =======, является версией в master ветке
||||||| 8b5b982
Изменения
=======
Все, что находится ниже =======, является версией в другой ветке
>>>>>>> test:index.html
Выбор одного из двух файлов для решения конфликтов
Оставить в конфликтном файле состояние ветки, В КОТОРУЮ мы вливаем:
git checkout --ours название_файла
Оставить в конфликтном файле состояние ветки, ИЗ КОТОРОЙ мы вливаем:
git checkout --theirs название_файла