Когда бы вы использовали разные стратегии 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ошибки, и благодаря этому сообщению в блоге ( зеркало ) я попытался "-с разрешить", который работал. Я до сих пор не совсем уверен, почему ... но я думаю, что это потому, что у меня были дублирующие изменения в обоих деревьях, и я решил "пропустить" их правильно.


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


-2

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.