Должен ли diff3 быть стандартным типом конфликтов в git?

Недавно я включил diff3, и теперь гораздо проще разрешить конфликт.

Ранее в некоторых случаях мне приходилось проверять журнал, чтобы понять, почему люди делали то или иное слияние. Но с diff3 информация отображается все в одном месте

<<<<<<< HEAD
THIS IS USEFUL
||||||| merged common ancestors
This is useful
=======
This is really useful
>>>>>>> c2392943.....

Из этого легко увидеть, что результат должен быть "ЭТО ДЕЙСТВИТЕЛЬНО ПОЛЕЗНО"

Интересно, есть ли недостатки у diff3? Почему это не стандартное поведение git?

5 ответов

Решение

Для других читателей (и из этой статьи):

Git имеет возможность отображать конфликты слияния в diff3 формат (по умолчанию отображаются только два файла для объединения). Вы можете включить его так:

git config --global merge.conflictstyle diff3

На самом деле нет причин, по которым вы не должны включать стиль diff3, потому что вам часто требуется, чтобы предок определил, каково правильное слияние.

Это было введено довольно рано (2008), и я полагаю, что это не значение по умолчанию, потому что стандартный unix diff не отображается как 3-way diff.


Как упоминалось в этом потоке, если вы хотите выполнить эту команду без настройки конфигурации, чтобы вы могли легко переключаться между обычными diff и diff3, это возможно в одном конкретном случае:

Если в индексе отмечен конфликт (т. Е. Состояние, в котором вы находитесь после конфликтующего слияния, но перед тем, как пометить путь как разрешенный), вы можете сделать следующее:

git checkout --conflict=diff3 <path...>

Обратите внимание, что фактически выполняется проверка содержимого индекса в рабочем дереве, поэтому любые изменения, внесенные вами в конфликтующую копию рабочего дерева, будут перезаписаны.

Еще один претендент на стиль конфликта слияния по умолчанию:, начиная с Git 2.35 (1 квартал 2022 г.): добавлен стиль представления конфликта слияния « Ревностный ».

См. коммит ddfc44a (1 декабря 2021 г.) Элайджи Ньюрена ( newren) .
См. (1 декабря 2021 г.) Филиппа Вуда ( phillipwood) .
(Объединено Junio ​​C Hamano -- gitster-- в коммите 4ce498b, 15 декабря 2021 г.)

коммит 4496526xdiff: реализовать рьяный diff3 или "zdiff3"

Основано на исправлении: Уве Кляйне-Кёниг
Соавтор: Элайджа Ньюрен
Подпись: Филипп Вуд
Подпись: Элайджа Ньюрен

"zdiff3" идентичен обычному, за исключением того, что он позволяет сжимать общие линии на двух сторонах истории в начале или конце куска конфликта.
Например, следующий конфликт:

       1
2
3
4
<<<<<<
A
B
C
D
E
||||||
5
6
======
A
X
C
Y
E
>>>>>>
7
8
9

имеет общие линии '', '' и '' с двух сторон.
Вместо этого можно было бы получить следующий конфликт:

       1
2
3
4
A
<<<<<<
B
C
D
||||||
5
6
======
X
C
Y
>>>>>>
E
7
8
9

Обратите внимание, что общие строки, ' A', и '' были вынесены за пределы конфликта.

В отличие от двусторонних конфликтов от «слияния» conflictStyle, конфликт НЕ разделяется на несколько конфликтных регионов, чтобы обеспечить общий ' C' строки должны быть показаны вне конфликта, потому что zdiff3также показывает базовую версию, и базовая версия не может быть разумно разделена.

Также обратите внимание, что удаление строк, общих для двух сторон, может привести к тому, что оставшийся текст внутри области конфликта совпадет с основным текстом внутри области конфликта (например, если diff3конфликт имел ' 5 6 E'на правой стороне конфликта, то общая линия' E' будет перемещен наружу, а оставшийся конфликтный текст как основной, так и правой стороны будет строками ' 5' а также ' 6').
Это может удивить пользователей и заставить их думать, что конфликта не должно было быть, но он определенно был и должен оставаться.

diff3должно быть по умолчанию. Это не только полезно для разрешения конфликтов, но и делает возможным разрешение конфликтов. Буквально невозможно правильно разрешить конфликты, используя (только) стиль конфликта слияния по умолчанию. Предлагаю всем установитьdiff3 в своих глобальных вариантах.

git config --global merge.conflictStyle diff3

Почему это буквально невозможно? Рассмотрим ветку, которая добавляет функциюfoo1 в определенном месте исходного файла

def foo1():
    print("foo1")

и еще одна ветка, которая добавляет функцию foo2 в том же месте

def foo2():
    print("foo2")

Если я переставлю один на другой, я получу конфликт. Будет отображаться стиль конфликта слияния по умолчанию

++<<<<<<< HEAD
 +def foo1():
 +    print("foo1")
++=======
+ def foo2():
+     print("foo2")
++>>>>>>> Add foo2

О чем мне говорят маркеры конфликта? Они говорят мне, что мне нужно добавить обаfoo1 а также foo2в файл, верно? К сожалению нет! Рассмотрим файл, в которомfoo1 а также foo2 уже существует, и две ветки, одна из которых удаляет foo1 и один из которых удаляет foo2. Если я переставлю один на другой, каков результат? Будет отображаться стиль конфликта слияния по умолчанию

++<<<<<<< HEAD
 +def foo1():
 +    print("foo1")
++=======
+ def foo2():
+     print("foo2")
++>>>>>>> Remove foo1

В стиле конфликта по умолчанию случай удаления двух функций полностью неотличим от случая добавления двух функций (кроме текста сообщения фиксации, которое может быть только подсказкой)! Следовательно, этого недостаточно для разрешения конфликтов. Это, вероятно, объясняет, почему разрешение конфликтов считается темным искусством. diff3 не только делает это возможным, но и часто упрощает.

Почему это не поведение git по умолчанию?

Я думаю, это не по умолчанию, потому что git mergetool в любом случае показывает 3 панели вверху: локальную, базовую (общий предок) и удаленную + 4-ю панель внизу, которая содержит контент, который вы пишете в своем вопросе.

Итак, если вы включите diff3 и использовать mergetool, тогда у вас будет дублироваться информация в средней верхней панели и в разделе между ||||||| и ======== на нижней панели.

Хотя я должен сказать, что мне очень нравится diff3, одним недостатком является то, что конфликты иногда имеют тенденцию быть больше.

И, конечно же, изменение значений по умолчанию для новых функций может сбить людей с толку.

Другие вопросы по тегам