diff 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
line wrap: on
line diff
--- a/mercurial/merge.py	Sat May 12 14:00:51 2012 +0200
+++ b/mercurial/merge.py	Thu May 03 15:14:58 2012 +0200
@@ -480,7 +480,8 @@
                 if f:
                     repo.dirstate.drop(f)
 
-def update(repo, node, branchmerge, force, partial, ancestor=None):
+def update(repo, node, branchmerge, force, partial, ancestor=None,
+           mergeancestor=False):
     """
     Perform a merge between the working directory and the given node
 
@@ -488,6 +489,10 @@
     branchmerge = whether to merge between branches
     force = whether to force branch merging or file overwriting
     partial = a function to filter file lists (dirstate not updated)
+    mergeancestor = if false, merging with an ancestor (fast-forward)
+      is only allowed between different named branches. This flag
+      is used by rebase extension as a temporary fix and should be
+      avoided in general.
 
     The table below shows all the behaviors of the update command
     given the -c and -C or no options, whether the working directory
@@ -548,7 +553,7 @@
                 raise util.Abort(_("merging with a working directory ancestor"
                                    " has no effect"))
             elif pa == p1:
-                if p1.branch() == p2.branch():
+                if not mergeancestor and p1.branch() == p2.branch():
                     raise util.Abort(_("nothing to merge"),
                                      hint=_("use 'hg update' "
                                             "or check 'hg heads'"))