Git: почему перебазирование приводит к конфликтам, а слияние - нет?

Я, наверное, что-то не понимаю, но может ли кто-нибудь объяснить мне, почему git rebase приводит к конфликтам, а git merge (та же ветвь) - нет?

Насколько я знаю, git rebase помещает коммиты из другой ветки перед коммитами, которые я сделал в моей текущей ветке, а git merge принимает те же самые коммиты и применяет их к моей ветке как патч, верно? Разве diff не то же самое, хотя, может быть, перевернутое? Не уверен, почему исправление моей ветки другими коммитами не проблема, а исправление другой ветки моими коммитами - это проблема.


person minitauros    schedule 15.07.2016    source источник


Ответы (2)


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

Допустим, у вас есть ветка master с коммитами A, B и C.

Затем из фиксации C вы создаете новую ветку mybranch. Вы делаете коммит, и вы получаете коммиты D и E.

Тем временем кто-то еще фиксирует F и G на мастере.

master тогда выглядит так: A B C F G, а mybranch выглядит так: A B C D E.

Теперь у вас есть две стратегии слияния:

Объединить

Находясь на mybranch, вы набираете git merge master. Он принимает все коммиты от master, которых у вас нет на mybranch - F и G. Сначала он объединяет F поверх вашего E (последняя фиксация mybranch), а затем объединяет G поверх F.

Конечный результат: A B C D E F G. Несмотря на то, что эти буквы находятся в одном порядке, фиксации не были выполнены (или, возможно, не были выполнены) в хронологическом порядке, потому что на самом деле F и G были (или могли быть) выполнены до D и E. В этом случае вы также увидите фиксацию слияния.

Rebase

Находясь на mybranch, вы набираете git rebase master. Он берет все коммиты из master, которых у вас нет в mybranch - F и G, и помещает их поверх текущей ветки, приводя ее в состояние, в котором сейчас находится master (потому что вы разветвились от master и теперь получаете все коммиты, которые были выполнены на master с тех пор, как вы разветвились). Затем он берет вашу первую фиксацию - D - и объединяет ее поверх G (последняя фиксация, сделанная master). Затем он берет E и кладет его поверх D.

Конечный результат: A B C F G D E. Похоже, что ни одна ветка никогда не отделялась master, и если мастер - это одна непрерывная работа, потому что вы как бы сказали: «Я хочу, чтобы моя ветка выглядела так, как если бы она была просто отделена от мастера, а затем моя работа была помещена поверх нее. ". Это эквивалент проверки master (сейчас A B C F G), создания новой ветки mybranch и последующего добавления ваших коммитов (A B C F G D E).

Почему перебазирование может привести к конфликту, а слияние - нет.

Не вдаваясь в подробности, давайте просто скажем, что слияние master F поверх mybranch E может не привести к конфликту, но слияние mybranch D поверх master F может. Это просто действительно зависит от того, какой код был изменен, и совместимо ли это изменение с предыдущей фиксацией. В обоих случаях могут возникнуть конфликты слияния.

person minitauros    schedule 08.07.2019

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

См. Также git rerere, который позволяет автоматически разрешать конфликты, которые вы уже решено.

person coredump    schedule 15.07.2016
comment
Я понимаю, о чем вы говорите, но все еще не понимаю. Скажем, моя ветка A фиксирует a, b и c. Затем я создаю ветку B с коммитами d и e. Фиксация f выполняется в ветви A. Rebase (в ветви B) приведет к: a, b, c, f, d, e; объединение приведет к: a, b, c, d, e, f. Каким же образом коммит f может создать конфликт слияния с коммитом c, если он изначально был создан поверх коммита c в ветке A? - person minitauros; 22.07.2016
comment
@minitauros (1) В результате слияния будут соединены две ветки: одна с a, b, c, f и одна с a, b, c, d, e, а не с линейной историей. (2) Если фиксация F, сделанная в ветке A, не приводит к конфликту, тогда я не понимаю, как это может привести к конфликту при перемещении (если у вас есть более подробный пример, это было бы здорово). (3) Но если D конфликтует с F и E исправляет этот конфликт, то при перезагрузке конфликт будет воспроизведен, а при слиянии - нет. - person coredump; 22.07.2016
comment
Хорошо, спасибо за объяснение! Немного проясняет. К сожалению, у меня больше нет этого примера (поскольку я его исправил), но если я снова столкнусь с ним и возникнет тот же вопрос, я обновлю этот пост дополнительной информацией :). На данный момент я думаю, что этот ответ достаточно хорош, спасибо! - person minitauros; 24.07.2016