почему во время выбора вишни возникает конфликт git?

Я использую git уже довольно давно, но никогда не понимал, почему возникают конфликты слияния. Я научился решать их быстро, но мне кажется, что непонимание того, почему они происходят, делает меня несчастным. Наиболее распространенное объяснение the same code region was changed by 2 different commits and now git cannot decide which one to pick имеет смысл только для самых простых случаев.

Чтобы лучше понять, что происходит, я создал простой файл с двумя строками:

a
b

и зафиксировал его (сообщение журнала init, мастер ветки).

Затем я создал ветку feat из master и добавил 3-ю строку: c

Затем я создал еще одну ветку feat2 из master и изменил b на bb.

Наконец, я изменил первую строку в master на ax.

В результате дерево выглядит так:

$ git tree
* f4c4a9d (feat) add 3rd line: c
| * f050bf8 (feat2) changed 2nd line: b -> bb
|/  
| * 244ed21 (HEAD -> master) change 1st line: a -> ax
|/  
* 51fca0f init

Если я хочу выбрать или объединить feat с мастером, он работает нормально, но если я хочу выбрать feat2, который изменяет вторую строку, он терпит неудачу и не может понять, почему это происходит.


person theluckyemil    schedule 11.12.2020    source источник
comment
Если вы не против сесть и почитать, вы можете взглянуть на то, что я пишу на эту тему: ezconflict. com (без отслеживания, без монетизации)   -  person eftshift0    schedule 11.12.2020
comment
Дубликат (например): Почему возникают изменения в другой строке git конфликт слияния? Как уже объяснил eftshift0, если одна ветвь (master) изменяет первую строку, а другая ветвь (feat2) изменяет вторую строку, это слишком близко друг к другу: это считается изменением двух одинаковых вещей. разными способами, т. е. конфликт.   -  person matt    schedule 12.12.2020
comment
Причины, почему это считается одним и тем же, немного сложны, но они связаны с алгоритмом сравнения (см. stackoverflow.com/questions/55275340 /)   -  person matt    schedule 12.12.2020


Ответы (2)


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

Имейте в виду, что вы рассматриваете не 2 версии файла, а три.

Одной из версий является общий предок (в вашем случае это действительно общий предок, но в случае выбора вишни это обычно не так):

a
b

Совет мастера:

ax
b

подвиг2:

a
bb

Если учесть, что осталось без изменений между тремя версиями, ничего не сохранилось.... так что мало что может сделать git, чтобы выяснить, что должно произойти. Вы получаете конфликт. Если бы между a и b была одна неизменная линия, проблем бы не было. Попробуйте внести те же изменения в a и b, но начиная с этого файла в первой версии:

a
x
b

Тогда у git нет проблем с выбором вишни. Было бы разумнее, если бы вы попытались выполнить слияние, используя merge.conflictStyle, установленное на diff3, чтобы вы могли видеть, как выглядит код в 3 задействованных версиях.

Дополнительное примечание: если вы не против сесть и почитать, вы можете взглянуть на то, что я пишу на эту тему (без монетизации, без отслеживания): http://www.ezconflict.com

person eftshift0    schedule 11.12.2020

Наиболее распространенное объяснение — одна и та же область кода была изменена двумя разными коммитами, и теперь git не может решить, какой из них выбрать, имеет смысл только для самых простых случаев.

Ну, нет... это именно объяснение, и оно применимо ко всем случаям. Деталь, которую вы можете упустить, заключается в том, что если между строками, затронутыми нашими изменениями, и строками, затронутыми их изменениями, нет хотя бы одной неизмененной строки, тогда изменения считаются перекрывающимися.

Итак, в вашем примере:

В master вы изменили первую строку.

В одной из веток вы добавили строку 3; так как линия 2 находится между ними, это не конфликт.

Но в другой ветке вы изменили строку 2. Между строками 1 и 2 нет строки, так что это будет противоречить изменению на master; и, кроме того, это будет противоречить добавлению строки 3 в другую ветку (поскольку между строкой 2 и строкой 3 нет строк).

person Mark Adelsberger    schedule 11.12.2020