Как мне указать базу слияния для использования в "HG слияния"

Я пытаюсь сделать сложное слияние в сложном хранилище HG. Я не доволен "новейшим общим предком", который Mercurial выбирает в качестве "базы" для выполнения слияния.

Я хотел бы указать конкретный коммит по своему выбору для использования в качестве базы.

Возможно ли это, и если да, то как?

3 ответа

Решение

Mercurial 3.0: теперь вы можете выбрать предка для использования в качестве базы слияния. Вы делаете это, устанавливая merge.preferancestor, Mercurial расскажет вам об этом, когда это будет иметь смысл. В приведенном ниже примере вы увидите:

$ hg merge
note: using eb49ad46fd72 as ancestor of 333411d2f751 and 7d1f71140c74
      alternatively, use --config merge.preferancestor=fdf4b78f5292
merging x
0 files updated, 1 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

Mercurial до версии 3.0: Lazy Badger правильно, что вы не можете выбрать предка, выбранного Mercurial при использовании его из командной строки. Тем не менее, вы можете сделать это внутри, и это не так уж сложно написать расширение для этого:

from mercurial import extensions, commands, scmutil
from mercurial import merge as mergemod

saved_ancestor = None

def update(orig, repo, node, branchmerge, force, partial, ancestor=None):
    if saved_ancestor:
        ancestor = scmutil.revsingle(repo, saved_ancestor).node()
    return orig(repo, node, branchmerge, force, partial, ancestor)

def merge(orig, ui, repo, node=None, **opts):
    global saved_ancestor
    saved_ancestor = opts.get('ancestor')
    return orig(ui, repo, node, **opts)

def extsetup(ui):
    extensions.wrapfunction(mergemod, 'update', update)
    entry = extensions.wrapcommand(commands.table, 'merge', merge)
    entry[1].append(('', 'ancestor', '', 'override ancestor', 'REV'))

Поместите это в файл и загрузите расширение. Теперь вы можете использовать

hg merge --ancestor X

переопределить нормального предка. Как вы узнали, это имеет значение, если есть несколько возможных предков. Такая ситуация возникает, если у вас есть перекрестные слияния. Вы можете создать такой случай с помощью этих команд:

hg init; echo a > x; hg commit -A -m a x
hg update 0; echo b >> x; hg commit -m b
hg update 0; echo c >> x; hg commit -m c
hg update 1; hg merge --tool internal:local 2; echo c >> x; hg commit -m bc
hg update 2; hg merge --tool internal:local 1; echo b >> x; hg commit -m cb

График выглядит так:

@    changeset: 4:333411d2f751
|\
+---o  changeset: 3:7d1f71140c74
| |/
| o  changeset: 2:fdf4b78f5292
| |
o |  changeset: 1:eb49ad46fd72
|/
o  changeset: 0:e72ddea4d238

Если вы сливаетесь нормально, вы получаете набор изменений eb49ad46fd72 как предок и файл x содержит:

a
c
b
c

Если вы вместо этого используете hg merge --ancestor 2 Вы получите другой результат:

a
b
c
b

В обоих случаях мой KDiff3 мог автоматически обрабатывать слияние, не сообщая о каких-либо конфликтах. Если я использую "рекурсивную" стратегию слияния и выберу e72ddea4d238 как предок, тогда у меня возник разумный конфликт. Git по умолчанию использует стратегию рекурсивного слияния.

База просто используется как еще один вход для вашего инструмента слияния. Если вы отключите premerge в вашей конфигурации инструмента слияния (premerge делает "очевидный выбор" для вас, когда нет конфликтов) и вызывает ваш инструмент слияния, вручную предоставляя копии 3 ревизий, которые вы хотите, как локальную, удаленную и базовую, вы можете получить все, что вы хотите в ваш инструмент слияния. Только левый родитель и правый родитель фактически записаны в слиянии.

Вы не можете сделать это. Потому что новейший общий предок является реальным основанием для вашего слияния

Если вы хотите выполнить слияние и не хотите переосмысливать (потому что ваши логические основы показывают / меня / неверные предположения и путь решения) вы можете пойти по пути исправления clone-rebase-merge-export-import

Другие вопросы по тегам