comparison mercurial/merge.py @ 27267:d6859d86a5d5

merge.graft: add option to keep second parent Currently merge.graft re-writes the dirstate so only a single parent is kept. For some cases, like evolving a merge commit, this behaviour is not desired. More specifically, this is needed to fix issue4389.
author Andrew Halberstadt <ahalberstadt@mozilla.com>
date Thu, 03 Dec 2015 23:01:59 -0500
parents 25e4b2f000c5
children 777f668eca70
comparison
equal deleted inserted replaced
27266:4dccc37b87bd 27267:d6859d86a5d5
1487 1487
1488 if not partial: 1488 if not partial:
1489 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3]) 1489 repo.hook('update', parent1=xp1, parent2=xp2, error=stats[3])
1490 return stats 1490 return stats
1491 1491
1492 def graft(repo, ctx, pctx, labels): 1492 def graft(repo, ctx, pctx, labels, keepparent=False):
1493 """Do a graft-like merge. 1493 """Do a graft-like merge.
1494 1494
1495 This is a merge where the merge ancestor is chosen such that one 1495 This is a merge where the merge ancestor is chosen such that one
1496 or more changesets are grafted onto the current changeset. In 1496 or more changesets are grafted onto the current changeset. In
1497 addition to the merge, this fixes up the dirstate to include only 1497 addition to the merge, this fixes up the dirstate to include only
1498 a single parent and tries to duplicate any renames/copies 1498 a single parent (if keepparent is False) and tries to duplicate any
1499 appropriately. 1499 renames/copies appropriately.
1500 1500
1501 ctx - changeset to rebase 1501 ctx - changeset to rebase
1502 pctx - merge base, usually ctx.p1() 1502 pctx - merge base, usually ctx.p1()
1503 labels - merge labels eg ['local', 'graft'] 1503 labels - merge labels eg ['local', 'graft']
1504 keepparent - keep second parent if any
1504 1505
1505 """ 1506 """
1506 # If we're grafting a descendant onto an ancestor, be sure to pass 1507 # If we're grafting a descendant onto an ancestor, be sure to pass
1507 # mergeancestor=True to update. This does two things: 1) allows the merge if 1508 # mergeancestor=True to update. This does two things: 1) allows the merge if
1508 # the destination is the same as the parent of the ctx (so we can use graft 1509 # the destination is the same as the parent of the ctx (so we can use graft
1512 mergeancestor = repo.changelog.isancestor(repo['.'].node(), ctx.node()) 1513 mergeancestor = repo.changelog.isancestor(repo['.'].node(), ctx.node())
1513 1514
1514 stats = update(repo, ctx.node(), True, True, False, pctx.node(), 1515 stats = update(repo, ctx.node(), True, True, False, pctx.node(),
1515 mergeancestor=mergeancestor, labels=labels) 1516 mergeancestor=mergeancestor, labels=labels)
1516 1517
1517 # drop the second merge parent 1518 pother = nullid
1519 parents = ctx.parents()
1520 if keepparent and len(parents) == 2 and pctx in parents:
1521 parents.remove(pctx)
1522 pother = parents[0].node()
1523
1518 repo.dirstate.beginparentchange() 1524 repo.dirstate.beginparentchange()
1519 repo.setparents(repo['.'].node(), nullid) 1525 repo.setparents(repo['.'].node(), pother)
1520 repo.dirstate.write(repo.currenttransaction()) 1526 repo.dirstate.write(repo.currenttransaction())
1521 # fix up dirstate for copies and renames 1527 # fix up dirstate for copies and renames
1522 copies.duplicatecopies(repo, ctx.rev(), pctx.rev()) 1528 copies.duplicatecopies(repo, ctx.rev(), pctx.rev())
1523 repo.dirstate.endparentchange() 1529 repo.dirstate.endparentchange()
1524 return stats 1530 return stats