Когда бы вы использовали разные стратегии git merge?

430

На странице руководства git-merge есть несколько стратегий слияния, которые вы можете использовать.

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

  • рекурсивный - это может разрешить только две головы с использованием алгоритма 3-way merge. Если для трехстороннего слияния можно использовать несколько общих предков, оно создает объединенное дерево общих предков и использует его в качестве ссылочного дерева для трехстороннего слияния. Сообщается, что это приводит к меньшему количеству конфликтов слияния, не вызывая слияний в результате тестов, выполненных на реальных коммитах слияния, взятых из истории разработки ядра Linux 2.6. Кроме того, это может обнаруживать и обрабатывать слияния, связанные с переименованием. Это стратегия слияния по умолчанию при извлечении или слиянии одной ветви.

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

  • ours - Это разрешает любое количество головок, но результатом слияния всегда является текущая головка. Он предназначен для замены старой истории развития боковых веток.

  • поддерево - это измененная рекурсивная стратегия. При объединении деревьев A и B, если B соответствует поддереву A, B сначала корректируется, чтобы соответствовать древовидной структуре A, вместо того, чтобы читать деревья на том же уровне. Эта корректировка также выполняется для общего дерева предков.

Когда я должен указать что-то отличное от значения по умолчанию? Какие сценарии лучше всего подходят для каждого?

Отто
источник

Ответы:

305

Я не знаком с решимостью, но я использовал другие:

рекурсивный

Рекурсивный является значением по умолчанию для слияний без ускоренной пересылки. Мы все знакомы с этим.

Осьминог

Я использовал осьминога, когда у меня было несколько деревьев, которые нужно было объединить. Вы видите это в более крупных проектах, где многие филиалы имели независимое развитие, и все они готовы объединиться в одну голову.

Ветвь осьминога объединяет несколько голов в один коммит, если он может делать это чисто.

Для иллюстрации представьте, что у вас есть проект с мастером, а затем три ветви для объединения (назовите их a, b и c).

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

серия рекурсивных слияний

Тем не менее, одиночное слияние осьминога будет выглядеть так:

commit ae632e99ba0ccd0e9e06d09e8647659220d043b9
Merge: f51262e... c9ce629... aa0f25d...

слияние осьминога

наш

Наша == Я хочу добавить другую голову, но выбросить все изменения, которые вносит эта голова.

Это сохраняет историю ветви без каких-либо эффектов ветви.

(Чтение: даже не рассматриваются изменения между этими ветвями. Ветви просто объединяются, и файлы ничего не предпринимаются. Если вы хотите объединиться с другой веткой, и каждый раз возникает вопрос "версия нашего файла или их версия "можно использовать git merge -X ours)

Subtree

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

Дастин
источник
1
Таким образом, единственным реальным преимуществом Ocotopus является уменьшение количества коммитов слияния в дереве?
Отто
60
Вам не нужно указывать стратегию слияния осьминога : она используется автоматически, если вы объединяете более двух ветвей ( git merge A B ...).
Якуб Наребски
Извините, что не по теме, но из какого инструмента вы сделали эти скриншоты? Похоже, действительно отличная визуализация истории ветвей ...
Бернд Хауг
4
Гитг для тех, кто в среде Linux.
Акаш Агравал
2
Этот намек -X oursпросто потрясающий, только что сэкономил мне час работы.
Майкл
49

На самом деле единственными двумя стратегиями, которые вы хотели бы выбрать, являются наши, если вы хотите отказаться от изменений, внесенных ветвью, но сохранить ветку в истории и поддерево, если вы объединяете независимый проект в подкаталог суперпроекта (например, «git-gui» in »). Git 'хранилище).

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

Якуб Наребски
источник
Мне пришлось выбрать 'resolv' вместо стандартного 'recursive' для слияния с двумя головами, которое имело фатальные ошибки git-write-tree. Стратегия «Разрешить» слилась чисто. Возможно, это связано с перемещением большого количества файлов в объединяемой ветви.
thaddeusmt
@thaddeusmt: Интересно. Не могли бы вы, если возможно, опубликовать отчет об ошибке в связи с этим провалом "рекурсивной" стратегии слияния в список рассылки git? Заранее спасибо.
Якуб Наребски
@ JakubNarębski Я не уверен, как собрать вместе достаточно информации, чтобы подать содержательный отчет об ошибке, я n00b с Git, извините. Как я уже упоминал в своем ответе здесь ( stackoverflow.com/a/10636464/164439 ), я предполагаю , что это связано со мной, дублируя изменения в обеих ветвях, а «resolv» лучше пропускает дублированные изменения.
thaddeusmt
@ JakubNarębski, теперь вы также можете выбрать их , что в соответствии с руководством «противоположно нашему» . Они не выбираются автоматически для вас. Можете ли вы немного обновить свой ответ, добавив вариант их
SebNag
3
@SebTu: нет theirsстратегии слияния (то есть --strategy=theirs), но есть theirsвариант recursiveстратегии слияния по умолчанию (то есть --strategy=recursive --strategy-option=theirsили просто -Xtheirs).
Якуб Наребски
23

"Решить" против "Рекурсивной" стратегии слияния

Рекурсивная текущая стратегия с двумя головами по умолчанию, но после некоторого поиска я наконец нашел некоторую информацию о стратегии слияния «решить».

Взято из книги О'Рейли « Контроль версий с помощью Git ( Amazon )» (перефразировано):

Первоначально, «разрешение» было стратегией по умолчанию для слияний Git.

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

Я успешно объединил деревья, используя «resolv», который не удался с рекурсивной стратегией по умолчанию. Я получал fatal: git write-tree failed to write a treeошибки, и благодаря этому сообщению в блоге ( зеркало ) я попытался "-с разрешить", который работал. Я до сих пор не совсем уверен, почему ... но я думаю, что это потому, что у меня были дублирующие изменения в обоих деревьях, и я решил "пропустить" их правильно.

оборота thaddeusmt
источник
Я использую трехстороннее слияние (p4merge), и у меня возникли конфликты, записанные в файл .BASE, когда не удалось выполнить рекурсивное слияние. Откат к решающей стратегии помог в этом случае.
mrzl
-2

Поскольку ответы выше не показывают все детали стратегии. Например, какой - то ответ отсутствует подробность о импортной resolveопции и recursiveкоторый имеет много вариантов , как к югу ours, theirs, patience, renormalizeи т.д.

Поэтому я бы порекомендовал посетить официальную gitдокументацию, в которой объясняются все возможные особенности функций:

https://git-scm.com/docs/merge-strategies

Рене Б.
источник