Каково простое объяснение этих маркеров слияния Git? - PullRequest
0 голосов
/ 15 мая 2019

Объясните значение маркеров слияния Git, приведенных ниже, со ссылкой на сегменты кода 1, 2 и 3.

/* Code from beginning of file */

<<<<<<< HEAD
      /* code segment 1 */
||||||| merged common ancestors
      /* code segment 2 */
=======
      /* code segment 3 */
>>>>>>> master

/* code to end of file */

Этот вопрос предназначен для того, чтобы получить простое объяснение без ссылки на извлекающие факторы, найденные вдругие вопросы.

1 Ответ

0 голосов
/ 15 мая 2019

Эти маркеры шевронного выхода (<<<<<<< и т. П.) Являются маркерами конфликта . Этот конкретный набор, который включает маркеры |||||||, относится к стилю конфликта 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 используется по умолчанию.

...