Ответ 1
То, что вы видите в этом примере (с маркерами Temporary merge branch
), является результатом diff3 с конфликтом с перекрестным слиянием. Я объясню это с помощью последовательности определений.
Определения
- слияние базы: фиксация, в которой две сходящиеся ветки, которые были недавно расставлены. Когда происходит конфликт слияния, в обеих ветвях были сделаны разные изменения в тех же строках. База слияния содержит то, что эти строки были до того, как любая ветвь изменила их.
- объединенные общие предки: diff3 выводит дополнительный "средний" раздел, показывающий линии, как они были в базе слияния. Это отправная точка для обеих ветвей.
- Criss-cross merge: история слияния, в которой две ветки сливаются друг с другом таким образом, что невозможно было бы ускорить слияние. Я приведу пример ниже. В ситуации слияния с перекрестным скрещиванием существует множество баз слияния.
- Временная ветвь слияния. Когда существует несколько баз слияния, diff3 пытается объединить их вместе (используя временные ветки слияния), чтобы сформировать единого общего предка, который будет показан в средней секции diff3. Это работает легко, когда конфликтов нет, но когда есть конфликты, вы видите временные маркеры конфликтов слияния в середине объединенных общих предков.
Пример сценария конфликта слияния с перекрестным скрещением
Слияние крест-крест происходит, когда две ветки сливаются друг с другом в разные моменты времени.
m3 *
|\
| \
| * B1
| |
m2 * * B0
|\/|
|/\|
m1 * * A
| /
|/
m0 *
Рассмотрим эту последовательность событий:
-
m0
существует как начало / m aster - Я создаю ветвь функции
feature-A
с одной фиксациейA
-
m1
получает обязательство владеть кем-то другим. - Я начинаю новую ветвь функции
feature-B
, которая строится наA
- Я объединяю
origin/master
(m1
) вfeature-B
. Это конфликтует, и я разрешаю это. Согласование слияния -B0
. - Я реализую функцию-B и выполняю работу как
B1
. -
feature-A
готов к отправке, поэтому кто-то объединяет его вmaster
. Это противоречит. Они разрешают это, но их разрешение отличается от резолюции вB0
. Согласование слияния -m2
. -
feature-B
готов к отправке, поэтому кто-то объединяет его вmaster
. git пытается определить базу слияния, ноm1
иA
оба одинаково квалифицируются как базы слияния. git объединяетm1
иA
во временную ветвь слияния, что приводит к конфликту. Мы видим вывод diff3 в разделе объединенных общих предков, аналогичном вопросу OP.
Чтение вывода
С diff3 off этот конфликт слияния будет выглядеть так:
<<<<<<< HEAD
aaaaaa
=======
hhhhhh
>>>>>>> mybranch
Во-первых, со всеми дополнительными маркерами вы захотите определить, каковы фактические конфликтующие строки, поэтому вы можете отличить его от вывода diff3 common ancestor.
aaaaaahhhhhh, это немного лучше.; -)
В случае, когда два разрешения конфликтов противоречат друг другу, aaaaaa
и hhhhhh
являются двумя разрешениями.
Затем рассмотрим содержимое объединенного общего предка.
С этой конкретной историей слияния существовало более двух баз слияния, что требовало нескольких временных ветвей слияния, которые затем были объединены. Результат, когда есть много оснований слияния и конфликтов, может стать довольно волосатым и трудночитаемым. Некоторые говорят, что не беспокойтесь, просто отключите diff3 для этих ситуаций.
Также имейте в виду, что git внутренне может решить использовать разные стратегии слияния для автоматического разрешения конфликтов, поэтому вывод может быть трудно понять. Почувствуйте это, если сможете, но знайте, что он не предназначен для потребления человеком. В этом случае возник конфликт при объединении mybranch
в Temporary merge branch 1
между bbbbbb
и cccccc
. Строка dddddd
не имела конфликтов между временными ветвями слияния. Затем возник отдельный конфликт при объединении Temporary merge branch 2
в HEAD
с несколькими общими предками. HEAD
разрешил конфликт, объединив ffffff
и gggggg
как eeeeee
, но Temporary merge branch 2
разрешил этот же конфликт, удалив (или двигая) строку (таким образом, нет строк между ======
и Temporary merge branch 2
.
Как вы разрешаете конфликт вроде этого? В то время как технический анализ может быть возможен, ваш самый безопасный вариант - это, как правило, вернуться назад и просмотреть историю во всех задействованных ветвях конфликта, и вручную создать разрешение, основанное на вашем понимании.
Избегайте всего этого
Эти конфликты являются наихудшими, но есть некоторые способы поведения, которые помогут предотвратить их.
-
Избегайте перекрестных слияний. В приведенном выше примере
feature-B
объединеноorigin/master
какB0
. Возможно, что это слияние, чтобы оставаться в курсе мастерства, не было необходимым (хотя иногда оно и есть). Еслиorigin/master
никогда не сливалось вfeature-B
, не было бы слияния criss-cross, аm3
было бы нормальным конфликтом сA
как единственной базой слияния.m3 * m3 * |\ |\ | \ | \ | * B1 | * B1 | | | | m2 * * B0 VS m2 * | |\/| |\ | |/\| | \| m1 * * A m1 * * A | / | / |/ |/ m0 * m0 *
- В соответствии с разрешениями конфликтов. В этом примере конфликт базы временного слияния возник только потому, что
m2
иB0
имели разные разрешения конфликтов. Если бы они разрешили конфликт одинаково,m3
было бы чистое слияние. Поймите, однако, что это простой крест-крест, который должен был иметь такое же разрешение. Другие ситуации могут по праву иметь разные разрешения. Все усложняется, когда между точками слияния имеется более двух баз слияния и нескольких коммитов. Тем не менее, если вы сознательно не согласны с разрешениями конфликтов в сложных ситуациях, ожидайте головные боли позже.