Тур по Git
Ветвление и слияние / Урок 2.11

Стратегии слияния -- ours, theirs, recursive

Когда вы выполняете git merge, Git не всегда объединяет изменения одинаково. Он выбирает стратегию слияния в зависимости от ситуации, и вы можете переопределить этот выбор. Понимание доступных стратегий даёт вам тонкий контроль над тем, как ветки объединяются.

По умолчанию: стратегия Recursive

Для большинства слияний двух веток Git использует стратегию recursive. Она находит общего предка обеих веток и выполняет трёхстороннее слияние, создавая коммит слияния, если ветки разошлись.

git merge feature
# Эквивалентно:
git merge --strategy=recursive feature

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

Опции стратегии: -X ours и -X theirs

Стратегия recursive принимает опции, которые управляют разрешением конфликтов:

git merge -X ours feature
git merge -X theirs feature
  • -X ours -- При возникновении конфликта автоматически выбирать нашу версию (текущая ветка)
  • -X theirs -- При возникновении конфликта автоматически выбирать их версию (сливаемая ветка)

Неконфликтующие изменения с обеих сторон по-прежнему сливаются нормально. Эти опции влияют только на строки, где обе ветки внесли разные изменения в одно и то же место.

Стратегия ours (это не то же самое!)

Существует совершенно другая стратегия под названием ours:

git merge --strategy=ours feature

Это создаёт коммит слияния, но полностью игнорирует изменения другой ветки. Результат идентичен содержимому текущей ветки. Другая ветка записывается как родитель (чтобы Git знал, что она была "слита"), но ни одно из её изменений не применяется.

Критическое различие

КомандаЧто она делает
git merge -X ours featureСливает нормально, автоматически разрешает конфликты в пользу нашей стороны
git merge --strategy=ours featureИгнорирует все изменения из feature, сохраняет наше дерево без изменений

Первая -- это предпочтение при разрешении конфликтов. Вторая -- способ пометить ветку как слитую, не принимая ни одного из её изменений.

Когда полезна --strategy=ours?

  • Закрытие ветки, которую вы не хотите сливать, но хотите пометить как "готовую"
  • Установление того, что ваша ветка заменяет другую без включения её изменений
  • Предотвращение будущих слияний от повторного внесения изменений из этой ветки

Стратегия theirs

Встроенной --strategy=theirs не существует, но вы можете добиться того же эффекта:

git merge -s ours feature    # помечает feature как слитую, сохраняет наше содержимое
# Чтобы сделать обратное (сохранить полностью их версию):
git merge -X theirs feature  # сливает, разрешая все конфликты в их пользу

Для настоящей "стратегии theirs" (полностью отбросить наши изменения) потребуется ручной подход, или можно использовать git merge -X theirs, что достаточно близко для большинства случаев.

Octopus-слияние

Когда нужно слить более двух веток одновременно, Git использует стратегию octopus:

git merge feature-a feature-b feature-c

Git автоматически выбирает стратегию octopus, когда указано несколько веток. Она хорошо работает, когда ветки не конфликтуют друг с другом -- например, когда разные команды работали над совершенно разными файлами.

Octopus-слияния не умеют обрабатывать конфликты. Если какая-либо ветка конфликтует с другой, Git прерывает операцию и просит вас сливать ветки по одной.

После octopus-слияния:
main:     A --- B ----------- M
                 \    \      /|
feature-a:        C    \   /  |
feature-b:         D    \/   |
feature-c:          E ---+---

Коммит слияния M имеет несколько родителей -- по одному на каждую слитую ветку.

Итог

СтратегияФлагСлучай использования
recursive (по умолчанию)--strategy=recursiveОбычное слияние двух веток
-X oursОпция recursiveАвтоматическое разрешение конфликтов в нашу пользу
-X theirsОпция recursiveАвтоматическое разрешение конфликтов в их пользу
ours--strategy=oursЗаписать слияние, но полностью отбросить их изменения
octopus--strategy=octopusСлияние нескольких веток одновременно (конфликты не допускаются)

Ключевая идея

Самый частый источник путаницы -- это --strategy=ours и -X ours. Запомните: стратегия определяет общий алгоритм, а -X опции настраивают разрешение конфликтов внутри этого алгоритма. Когда кто-то говорит "слей с ours", всегда уточняйте, что именно имеется в виду.