[PATCH 2 of 2] branch: make it possible to gently (without force) revive an ancestor branch

Mads Kiilerich mads at kiilerich.com
Fri Aug 29 05:22:45 CDT 2014


# HG changeset patch
# User Mads Kiilerich <madski at unity3d.com>
# Date 1408124612 -7200
#      Fri Aug 15 19:43:32 2014 +0200
# Node ID 07b14258740026ef01bcf754da382c22e71b1d7c
# Parent  104cfce5efd2e557801dd45dba6e35b056b8f3d2
branch: make it possible to gently (without force) revive an ancestor branch

Sometimes, when using named branches, it is convenient to merge the wrong way
and then fix the branch name after the merge before the commit. One example is
when reviving an old release branch and you don't want to update to the old
branch head and recompile everything.

Forcible switching to another existing branch is normally not possible without
force. It has however "always" (b2873c587b1a) been possible to gently switch
to one of the parent branches.

Merging "the wrong way" is however not always possible - it has often already
been merged and doing it again will thus be a merge with a working directory
ancestor.

For symmetry, it should thus also be possible to gently switch to another
branch if the branch head is working directory ancestor.

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1033,7 +1033,10 @@ def branch(ui, repo, label=None, **opts)
             ui.status(_('reset working directory to branch %s\n') % label)
         elif label:
             if not opts.get('force') and label in repo.branchmap():
-                if label not in [p.branch() for p in repo.parents()]:
+                if (label not in [p.branch() for p in repo.parents()] and
+                    not util.any(repo.changelog.isancestor(repo[label].node(),
+                                                           p.node())
+                                 for p in repo.parents())):
                     raise util.Abort(_('a branch of the same name already'
                                        ' exists'),
                                      # i18n: "it" refers to an existing branch
diff --git a/tests/test-newbranch.t b/tests/test-newbranch.t
--- a/tests/test-newbranch.t
+++ b/tests/test-newbranch.t
@@ -31,9 +31,8 @@
 Branch shadowing:
 
   $ hg branch default
-  abort: a branch of the same name already exists
-  (use 'hg update' to switch to it)
-  [255]
+  marked working directory as branch default
+  (branches are permanent and global, did you want a bookmark?)
 
   $ hg branch -f default
   marked working directory as branch default
@@ -86,9 +85,8 @@ Merging and branches
  set existing branch name where branch head is ancestor:
 
   $ hg branch bar
-  abort: a branch of the same name already exists
-  (use 'hg update' to switch to it)
-  [255]
+  marked working directory as branch bar
+  (branches are permanent and global, did you want a bookmark?)
 
  set (other) parent branch as branch name
 


More information about the Mercurial-devel mailing list