Как мне указать базу слияния для использования в "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