comparison mercurial/merge.py @ 16696:d1afbf03e69a

rebase: allow collapsing branches in place (issue3111) We allow rebase plus collapse, but not collapse only? I imagine people would rebase first then collapse once they are sure the rebase is correct and it is the right time to finish it. I was reluctant to submit this patch for reasons detailed below, but it improves rebase --collapse usefulness so much it is worth the ugliness. The fix is ugly because we should be fixing the collapse code path rather than the merge. Collapsing by merging changesets repeatedly is inefficient compared to what commit --amend does: commitctx(), update, strip. The problem with the latter is, to generate the synthetic changeset, copy records are gathered with copies.pathcopies(). copies.pathcopies() is still implemented with merging in mind and discards information like file replaced by the copy of another, criss-cross copies and so forth. I believe this information should not be lost, even if we decide not to interpret it fully later, at merge time. The second issue with improving rebase --collapse is the option should not be there to begin with. Rebasing and collapsing are orthogonal and a dedicated command would probably enable a better, simpler ui. We should avoid advertizing rebase --collapse, but with this fix it becomes the best shipped solution to collapse changesets. And for the record, available techniques are: - revert + commit + strip: lose copies - mq/qfold: repeated patching() (mostly correct, fragile) - rebase: repeated merges (mostly correct, fragile) - collapse: revert + tag rewriting wizardry, lose copies - histedit: repeated patching() (mostly correct, fragile) - amend: copies.pathcopies() + commitctx() + update + strip
author Patrick Mezard <patrick@mezard.eu>
date Thu, 03 May 2012 15:14:58 +0200
parents 525fdb738975
children e7bf09acd410
comparison
equal deleted inserted replaced
16695:0a0933d3d59c 16696:d1afbf03e69a
478 else: 478 else:
479 repo.dirstate.normal(fd) 479 repo.dirstate.normal(fd)
480 if f: 480 if f:
481 repo.dirstate.drop(f) 481 repo.dirstate.drop(f)
482 482
483 def update(repo, node, branchmerge, force, partial, ancestor=None): 483 def update(repo, node, branchmerge, force, partial, ancestor=None,
484 mergeancestor=False):
484 """ 485 """
485 Perform a merge between the working directory and the given node 486 Perform a merge between the working directory and the given node
486 487
487 node = the node to update to, or None if unspecified 488 node = the node to update to, or None if unspecified
488 branchmerge = whether to merge between branches 489 branchmerge = whether to merge between branches
489 force = whether to force branch merging or file overwriting 490 force = whether to force branch merging or file overwriting
490 partial = a function to filter file lists (dirstate not updated) 491 partial = a function to filter file lists (dirstate not updated)
492 mergeancestor = if false, merging with an ancestor (fast-forward)
493 is only allowed between different named branches. This flag
494 is used by rebase extension as a temporary fix and should be
495 avoided in general.
491 496
492 The table below shows all the behaviors of the update command 497 The table below shows all the behaviors of the update command
493 given the -c and -C or no options, whether the working directory 498 given the -c and -C or no options, whether the working directory
494 is dirty, whether a revision is specified, and the relationship of 499 is dirty, whether a revision is specified, and the relationship of
495 the parent rev to the target rev (linear, on the same named 500 the parent rev to the target rev (linear, on the same named
546 if branchmerge: 551 if branchmerge:
547 if pa == p2: 552 if pa == p2:
548 raise util.Abort(_("merging with a working directory ancestor" 553 raise util.Abort(_("merging with a working directory ancestor"
549 " has no effect")) 554 " has no effect"))
550 elif pa == p1: 555 elif pa == p1:
551 if p1.branch() == p2.branch(): 556 if not mergeancestor and p1.branch() == p2.branch():
552 raise util.Abort(_("nothing to merge"), 557 raise util.Abort(_("nothing to merge"),
553 hint=_("use 'hg update' " 558 hint=_("use 'hg update' "
554 "or check 'hg heads'")) 559 "or check 'hg heads'"))
555 if not force and (wc.files() or wc.deleted()): 560 if not force and (wc.files() or wc.deleted()):
556 raise util.Abort(_("outstanding uncommitted changes"), 561 raise util.Abort(_("outstanding uncommitted changes"),