Patchwork [2,of,2,v2] branch: make it possible for --new to revive an ancestor branch

login
register
mail settings
Submitter Mads Kiilerich
Date April 16, 2015, 8:13 p.m.
Message ID <a62ea67abdfb429faa46.1429215228@localhost.localdomain>
Download mbox | patch
Permalink /patch/8727/
State Rejected
Headers show

Comments

Mads Kiilerich - April 16, 2015, 8:13 p.m.
# HG changeset patch
# User Mads Kiilerich <madski@unity3d.com>
# Date 1408124612 -7200
#      Fri Aug 15 19:43:32 2014 +0200
# Node ID a62ea67abdfb429faa46f23ee987e62c61c2f2da
# Parent  d8e2697b4ca385bfcf944b897dad28fb57e3bcd6
branch: make it possible for --new to revive an ancestor branch

It deserves a warning/error when a new branch head is added ... and that is how
it always has been and will remain.

It does however also make perfect sense to let the branch command branch back
to an old branch if the existing branch head is an ancestor of the new one. It
will give a new use of the branch but it will not create a new branch head - it
will create a new changeset that is a new branch head and replaces an old one.

This functionality would perhaps be an unfortunate change of behaviour for the
old branch creation command - some users could believe they were updating to
the existing branch head. The new branch --new option makes it clear that we
not are updating and can revive the branch without force.
Matt Mackall - April 17, 2015, 12:32 a.m.
On Thu, 2015-04-16 at 16:13 -0400, Mads Kiilerich wrote:
> # HG changeset patch
> # User Mads Kiilerich <madski@unity3d.com>
> # Date 1408124612 -7200
> #      Fri Aug 15 19:43:32 2014 +0200
> # Node ID a62ea67abdfb429faa46f23ee987e62c61c2f2da
> # Parent  d8e2697b4ca385bfcf944b897dad28fb57e3bcd6
> branch: make it possible for --new to revive an ancestor branch

I'm not sold on this yet, so I'm going to have to defer it to post-3.4.

Patch

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1110,7 +1110,12 @@  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 (new and
+                    util.any(repo.changelog.isancestor(repo[label].node(),
+                                                       p.node())
+                             for p in repo.parents())):
+                    pass # reviving old branch head
+                elif label not in [p.branch() 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
@@ -28,7 +28,7 @@ 
   (branches are permanent and global, did you want a bookmark?)
   $ hg ci -m "change branch name"
 
-Branch shadowing:
+Branch shadowing - only possible with --new on ancestor or with force:
 
   $ hg branch default
   abort: a branch of the same name already exists
@@ -42,6 +42,16 @@  Branch shadowing:
   $ hg ci -m "clear branch name"
   created new head
 
+  $ hg branch --new foo
+  marked working directory as branch foo
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg up -qC 0
+
+  $ hg branch --new foo
+  abort: a branch of the same name already exists
+  (use 'hg update' to switch to it)
+  [255]
+
 There should be only one default branch head
 
   $ hg heads .