Последствия использования графта в Mercurial

98

В последнее время возникло несколько вопросов о пропуске изменений при поддержке веток выпуска в Mercurial. Например:

Поскольку он был представлен в 2.0, я задумался об использовании, graftчтобы избежать этой проблемы. Учитывая такое дерево ревизий:

A---B---C---D---E---F---G---H---I---J

Предположим, нам нужно создать ветку выпуска, которая пропускает изменение Evil E.

hg update -r D
hg graft "F::J"

давая нам:

A---B---C---D---E---F---G---H---I---J
             \
              --F'--G'--H'--I'--J'
  • Q1: Что здесь только что произошло? Я понимаю, что это transplantпривело бы к сгенерированию патчей F::J, а затем к их применению D, но, graftкак говорят, использовалось трехстороннее слияние, а не патчи. Итак ....... как это работает? Почему лучше?

Допустим, я сейчас исправлю Eи добавлю это в свою ветку выпуска.

                  --E2-----------------
                 /                     \
A---B---C---D---E---F---G---H---I---J---M1
             \                            \
              --F'--G'--H'--I'--J'---------M2--

M1 - прямое слияние; там ничего особенного. M2 объединяет ветки, в которых есть «такие же» (или, по крайней мере, эквивалентные) изменения.

  • Q2: Является ли это слияние просто обычная 3-полосная слияние с использованием D, J'а M1?
  • В3: Сохраняла ли Mercurial / использовала дополнительную информацию об операции трансплантата, чтобы помочь ей при слиянии?

И наконец...

  • Q4: Каковы потенциальные проблемы с таким потоком?
Пол С
источник

Ответы:

119

Когда вы обновляете Dи привязываете F::J, Mercurial выполняет ряд слияний. Это начнется с этого слияния:

M = three_way_merge(local=D, other=F, base=E)

Если мы пишем +dдля дельты между состояниями Cи D, то начинаем с:

        +d     +e     +f
---- C ---- D ---- E ---- F ----

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

    -e  
  .---- D
 /
E
 \
  '---- F
    +f

То есть мы делаем вид, что начали, Eи применяем противоположность, -eчтобы добраться до D. Я думаю как об обратном патче +e. Начиная с, Eмы также перешли в состояние Fс нормальной дельтой +f. Там нет ничего странного здесь - у нас есть все государства ( D, Eи F) в хранилище уже. Таким образом, видно, что мы можем объединить Dи F.

Слияние - это вопрос «завершения ромба». Таким образом , мы находим новое состояние , Mкоторое является сочетанием Dи Fи где разница от Dдо Mаналогична +fи разница от Fдо Mаналогична -e. Выглядит это так:

    -e     +f'
  .---- D ----.
 /             \
E               M
 \             /
  '---- F ----'
    +f     -e'

+fДельта стала +f'и -eдельта стала -e'. Это просто обычное трехходовое слияние, но эффект интересен: мы применили Fна Dвместо E!

После слияния второй родительский элемент Mto Fудаляется:

    -e     +f'
  .---- D ----.
 /             \
E               M
 \
  '---- F
    +f

Повторяю: мы скопировали «эффект» Fна D, то есть мы нашли delta ( +f'), которая применяется, чтобы Dдать тот же эффект, что и при +fприменении E. Мы можем немного выпрямить график, чтобы получить:

       +f'
--- D ---- M
     \
      '---- E ---- F
        +e     +f

В результате это Fпрививается Dс использованием полного трехходового механизма.

  • Q1: Что здесь только что произошло? Итак ....... как это работает? Почему лучше?

    О1: Использование слияния лучше, чем патчей, поскольку механизм слияния принимает во внимание такие вещи, как переименование.

  • Q2: Это слияние просто обычное трехстороннее слияние с использованием D, J 'и M1?

    A2: Да, прививка не меняет топологию графа.

  • В3: Сохраняла ли Mercurial / использовала дополнительную информацию об операции трансплантата, чтобы помочь ей при слиянии?

    A3: Нет.

  • Q4: Каковы потенциальные проблемы с таким потоком?

    A4: С точки зрения слияния все должно работать нормально. Это будет дублировать некоторую историю, которая может запутать людей.

Мартин Гейслер
источник
4
Отличный вопрос, отличный ответ :). +1 к обоим!
Лоуренс Холст
Спасибо, Мартин. Это довольно забавная мысль того, кто это придумал. Идея у меня есть, но нужно разобраться в общем случае. Я предполагаю, что это справедливо независимо от пути между узлами, к которым вы прививаете / из?
Paul S
3
@PaulS: Я думаю, все, что вам нужно знать, это то, что Graft может копировать ревизии более надежным способом, чем трансплант. Надежный в том смысле, что обрабатываются переименования и что вы можете разрешать конфликты с помощью инструмента слияния. Детали заключаются в странных слияниях, которые он делает, но, надеюсь, это не важно для повседневного использования трансплантата! :-)
Мартин Гейслер
3
Нет, но я любитель разбираться в вещах, которые мне не нужны ;-) Я проработал более общий пример, в любом случае используя ваш как основу.
Paul S,
@PaulS Если так, то я почти боюсь говорить вам об этом ... но вы можете найти Darcs и его теорию патчей. Приведенный выше трюк с поворотом графика на 90 градусов во многом напоминает мне то, как они говорят о коммутации патчей при слиянии. Довольно волосатая штука :-)
Мартин Гейслер
6

Q1: Это помогает, когда есть конфликты. Тогда вы можете использовать свой обычный инструмент слияния (для меня это встроенные маркеры конфликтов, которые я редактирую в smerge-режиме Emacs).

Q2: Это нормальное слияние.

Q3: Нет.

Q4: Я считаю некрасивым иметь две почти одинаковые ветки.

Звон
источник