Коли ви використовуєте різні стратегії злиття git?


429

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

  • вирішити - це може вирішити лише дві голови (тобто поточну гілку та іншу гілку, з якої ви витягли) за допомогою 3-х алгоритму злиття. Він намагається ретельно виявити двозначні незрозумілі злиття і вважається загалом безпечним і швидким.

  • рекурсивний - це може вирішити лише дві голови за допомогою 3-х алгоритму злиття. Коли існує більше одного спільного предка, який може бути використаний для тристороннього злиття, він створює об'єднане дерево спільних предків і використовує це в якості еталонного дерева для тривимірного злиття. Повідомлялося, що це призводить до меншої кількості конфліктів злиття, не викликаючи помилок злиття за допомогою тестів, зроблених на фактичних комісіях злиття, взятих з історії розробки ядра Linux 2.6. Крім того, це може виявити та обробити злиття, що включають перейменування. Це стратегія злиття за замовчуванням під час витягування або об'єднання однієї гілки.

  • восьминога - це вирішує більше, ніж двоголовий випадок, але відмовляється робити складне злиття, яке потребує ручного дозволу. Він в першу чергу призначений для використання для згуртування головок галузей тематики разом. Це стратегія злиття за замовчуванням при витягуванні або злитті декількох гілок.

  • наша - Це вирішує будь-яку кількість голів, але результатом злиття завжди є поточна голова філії. Він призначений для використання для витіснення старої історії розвитку бічних гілок.

  • subtree - Це модифікована рекурсивна стратегія. При злитті дерев A і B, якщо B відповідає піддереву A, B спочатку коригується відповідно до структури дерева A, замість зчитування дерев на тому ж рівні. Це коригування також робиться для звичайного дерева предків.

Коли я повинен вказати щось інше, ніж за замовчуванням? Які сценарії найкращі?

Відповіді:


305

Я не знайомий з рішенням, але я використовував інші:

Рекурсивний

Рекурсивний - це за замовчуванням для нешвидкісних злиття вперед. Ми всі з цим знайомі.

Восьминіг

Я використовував восьминога, коли у мене було кілька дерев, які потрібно було об’єднати. Ви бачите це у великих проектах, де багато галузей мали незалежний розвиток, і все готово об'єднатися в одну голову.

Гілка восьминога з’єднує кілька головок за один прийом, доки вона може це робити чисто.

Для ілюстрації, уявіть, що у вас є проект, у якого є майстер, а потім три гілки для злиття (назвіть їх a, b і c).

Серія рекурсивних об'єднань виглядатиме так (зауважте, що перше злиття було швидким вперед, оскільки я не примушував рекурсії):

серія рекурсивних злиття

Однак одне злиття восьминога виглядатиме так:

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

восьминога зливається

Наші

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

Це зберігає історію філії без жодного впливу її.

(Читайте: навіть не розглядається зміни між цими гілками. Гілки просто об'єднуються і нічого не робиться для файлів. Якщо ви хочете об'єднатись в іншу гілку і кожен раз виникає питання "наша версія файлу або їх версія "ви можете використовувати git merge -X ours)

Піддерево

Піддерево корисно, коли ви хочете об'єднати інший проект у підкаталог вашого поточного проекту. Корисно, коли у вас є бібліотека, яку ви не хочете включати як підмодуль.


1
Тож єдиною реальною перевагою Окотопа є зменшення кількості об'єднань у дереві?
Отто

60
Не потрібно вказувати стратегію злиття восьминога : вона використовується автоматично, якщо ви об'єднаєте більше двох гілок ( git merge A B ...).
Якуб Нарубський

Вибачте за те, що вийшов за тему, але що це за інструмент, для якого ви зробили ці скріншоти? Це схоже на справді чудову / гарну візуалізацію історії філії ...
Бернд Хауг,

4
gitg для тих, хто знаходиться в середовищі Linux.
Акаш Агравал

2
Цей натяк з -X oursприголомшливим, просто врятував мені годину роботи.
Майкл

49

Насправді єдиними двома стратегіями, які ви хочете вибрати, є наша, якщо ви хочете відмовитися від змін, внесених за галуззю, але зберегти гілку в історії та піддерево, якщо ви об'єднаєте незалежний проект у підкаталог суперпроекту (наприклад, 'git-gui' in ') git 'сховище).

Злиття восьминога використовується автоматично при злитті більше двох гілок. вирішення тут в основному з історичних причин, і коли ви потрапляєте в кутові випадки рекурсивної стратегії злиття.


Мені довелося обрати "вирішити" замість "рекурсивного" за замовчуванням для злиття двома головами, яке мало фатальні помилки дерева-git-write. Стратегія "вирішити" злилася чисто. Це, можливо, було пов'язано з переміщенням багатьох файлів у об'єднаній гілці.
thaddeusmt

@thaddeusmt: Цікаво. Не могли б ви, якщо це можливо, опублікувати повідомлення про помилку про цю невдачу "рекурсивної" стратегії об'єднання до списку розсилки git? Заздалегідь спасибі.
Якуб Нарбський

@ JakubNarębski Я не впевнений, як би я зібрав достатньо інформації, щоб подати змістовний звіт про помилку, я n00b з Git, вибачте. Як я згадую у своїй відповіді тут ( stackoverflow.com/a/10636464/164439 ), я здогадуюсь , що мені довелося робити дублювання змін в обох гілках, а "вирішити" краще, ніж пропустити дублювані зміни.
thaddeusmt

@ JakubNarębski тепер ви можете також вибрати з Їх , який в відповідно до інструкції "протилежністю наших . Їх не є ні автоматично вибираються для вас Можете ви можете злегка оновити anwser, додавши. Їхній варіант
SebNag

3
@SebTu: немає theirsстратегії злиття (тобто --strategy=theirs), але є theirsможливість recursiveстратегії злиття за замовчуванням (тобто --strategy=recursive --strategy-option=theirs, або просто -Xtheirs).
Якуб Нарубський

23

Стратегія "Розв’язати" проти "Рекурсивної"

Рекурсивна - це поточна стратегія з двома головами за замовчуванням, але після деяких пошуків я нарешті знайшов інформацію про стратегію злиття "вирішити".

Взято з книги O'Reilly Book Control Version with Git ( Amazon ) (перефразовано):

Спочатку "вирішити" була стратегія за замовчуванням для злиття Git.

У ситуаціях перехресного злиття, де існує більше ніж одна можлива основа злиття, стратегія вирішення працює так: виберіть одну з можливих основ злиття та сподівайтеся на найкраще. Це насправді не так погано, як це звучить. Часто виявляється, що користувачі працювали над різними частинами коду. У такому випадку Git виявляє, що повторює зміни, які вже є, і пропускає повторювані зміни, уникаючи конфлікту. Або, якщо це незначні зміни, які викликають конфлікт, принаймні конфлікт повинен бути простим для вирішення розробника.

Я успішно об'єднав дерева, використовуючи "вирішити", який не вдався до рекурсивної стратегії за замовчуванням. Я отримував 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.