Эти маркеры шевронного выхода (<<<<<<<
и т. П.) Являются маркерами конфликта . Этот конкретный набор, который включает маркеры |||||||
, относится к стилю конфликта diff3
. Стиль конфликта merge
по умолчанию опускает среднюю часть.
Секции в первой части, от <<<<<<<
до |||||||
, взяты из текущего коммита . Секции во второй части, с |||||||
по =======
, взяты из базы слияния (которую мы определим чуть позже). Разделы в третьей части, от =======
до >>>>>>>
, взяты из other commit.
длиннее, но полезнее
Чтобы понять, что это значит, помните, что любая операция git merge
имеет не два, а три входа. Один из трех входов - это ваша текущая проверка, также известная как HEAD
или @
commit. Обычно это самый новый коммит в ветке, которую вы проверили. Второй ввод основан на введенной вами команде git merge
. 1 Например, если вы запустили:
git merge theirbranch
тогда второй вход - это коммит в конце ветви theirbranch
; если вы бежали:
git merge origin/master
тогда второй вход - это коммит, на который указывает origin/master
. В любом случае, оба они являются коммитами - снимками, полными файлов, где файлы в вашем HEAD
коммите совпадают или отличаются от файлов в их коммите. Различия между вашими файлами и их файлами не имеют прямого отношения: ключевой коммит - это третий коммит, называемый base merge base .
Git автоматически находит для вас коммит базы слияния. По сути, база слияния - это лучший общий коммит , который предшествует двум другим. Помните, что цель объединения - объединить работу , и для этого Git должен выяснить , что вы изменили и , что они изменили . Но каждый коммит - это снимок, а не набор изменений, поэтому Git должен работать в обратном направлении от вашего коммита и его коммита, чтобы найти коммит, которым вы оба поделились при запуске. Это база слияния.
Найдя базу слияния, Git теперь выполняет два различий. Один сравнивает базу слияния с вашим текущим коммитом: это то, что вы изменили. Второй diff сравнивает базу слияния с их коммитом: вот что они изменили. Затем Git объединяет два набора изменений. Объединенные изменения применяются к базе слияния, чтобы получить окончательный результат слияния.
Когда вы изменяете файл, а он вообще не касается файла, объединение ваших изменений с их ничем означает, что результатом будут ваши изменения. Применение их к базовому файлу создает ваш файл. Аналогично, когда они меняют файл, а вы нет, объединение вашего ничто с их изменениями означает, что результатом являются их изменения, а применение их к базовому файлу дает их файл. Так что это очень просто.
Сложная часть возникает, когда вы и они оба изменили один и тот же файл. Теперь Git действительно должен объединять различные изменения. Если ваши изменения касаются строк, которых они не касались, и их изменения касаются строк, которых вы не трогали, Git может объединить их: он просто принимает оба изменения. Если вы изменили какую-то строку, и они внесли точно такое же изменение , Git также может объединить это: он просто берет одну копию изменения. действительно сложная часть, которая приводит к конфликту слияния, возникает, когда вы изменили несколько строк, и они изменили те же строки , иным способом.
В этом случае Git записывает конфликтующие изменения в копию файла рабочего дерева, окруженную этими маркерами конфликта.Часть над областью маркера конфликта была успешно объединена - или, по крайней мере, Git считает, что - имеет, - то же самое относится к части под областью маркера.В промежуточной части Git не может решить, предпочитаете ли вы ваши изменения в первом сегменте или их изменения в последнем.Средняя часть, показанная только при выборе стиля diff3
, выглядит так, как выглядели исходные линии.
1 Обратите внимание, что если вы запустили git pull
, чтобы добраться до этоготочка, git pull
побежал git merge
для вас.Так что вы, возможно, не запускали git merge
напрямую, но вы вызывали git merge
.
Команды cherry-pick и revert также используют механизм слияния Git.Так же поступают git stash
и некоторые случаи git apply
или git am
.Таким образом, вы можете увидеть эти конфликты слияния и для этих команд.Однако определение базы слияния для этих операций отличается, поэтому становится сложнее увидеть, как возник конфликт.
Еще один побочный эффект diff3 против слияния
Когда возникает конфликт, если у вас выбран стиль diff3
, Git должен показать вам базовую версию - весь раздел, где происходит конфликт.Но когда у вас выбран стиль merge
, Git может опустить базовую версию и показать только версии --ours
и --theirs
.Это означает, что если он может частично объединить конфликтующую область, он делает это, оставляя только область uncombined , окруженную маркерами.Например:
<<<<<<< HEAD
please fix a spelling error
and ok, I changed this
||||||| merged common ancestors
please fix a speeling error
and change this
=======
please fix a spelling error
and change this to something different
>>>>>>> theirs
Здесь мы и они исправили орфографическую ошибку таким же образом (заменив speeling
на spelling
), но мы изменили вторую строку иначе .В стиле diff3 вы видите базовую версию и обе конечные версии.
Если мы выберем стиль merge
, Git увидит, что мы и они исправили орфографическую ошибку одинаково, и вместо этого мы увидим:
please fix a spelling error
<<<<<<< HEAD
and ok, I changed this
=======
and change this to something different
>>>>>>> theirs
Часто это довольно мило - но иногда это означает, что вы не можете вообще сказать , что было исходной базой, потому что конфликт между чем-то и ничего , то есть один из нас или них удалил строку, когда другой из нас или них изменил это.Я считаю, что стиль diff3
гораздо легче читать, но стиль merge
используется по умолчанию.