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

login
register
mail settings
Submitter Mads Kiilerich
Date April 15, 2015, 9:14 p.m.
Message ID <f832f9a6081a18eb3f54.1429132491@localhost.localdomain>
Download mbox | patch
Permalink /patch/8692/
State Rejected
Headers show

Comments

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

It deserves a warning/error when creating a new branch head ... 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. The
new use of the branch will be new but it will not create a new branch head - it
will create a new changeset that is a new branch head and replaces another one.
There is thus no reason to issue any warning in that case.

This functionality would perhaps be an unfortunate change of behaviour for the
old branch creation command - git users could easily think they were switching
the existing branch head. We can however do it with the new branch --new
option.

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 # continuing 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,14 @@  Branch shadowing:
   $ hg ci -m "clear branch name"
   created new head
 
+  $ hg branch --new foo
+  $ 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 .