Issue1974

Title Cannot create new remote head on named branch without --force
Priority bug Status resolved
Superseder Nosy List Pike, ThomasAH, abuehl, cyanite, hgbot, hstuart, jan1972, jglick, marcusl, mg, tuukka
Assigned To cyanite Topics named branches, push

Created on 2010-01-07.15:41:50 by jglick, last changed 2010-07-13.15:44:58 by jglick.

Messages
msg13094 (view) Author: jglick Date: 2010-07-13.15:44:58
I see. In fact it was referring to: http://bugs.python.org/issue1974
msg13093 (view) Author: marcusl Date: 2010-07-13.15:14:46
The commit msg mentions this issue:

---
mail: ensure that Python2.4 to 2.7 use the same header format

Wrapping format for long headers changed in Python2.7 (see Python issue1974).
Adopt the Python2.7 behaviour and backport it for 2.4-2.6
---
msg13092 (view) Author: jglick Date: 2010-07-13.15:06:15
Not sure what that was about; mentioned cset has no apparent relation to
this issue.
msg13089 (view) Author: hgbot Date: 2010-07-13.15:00:06
Fixed by http://hg.intevation.org/mercurial/crew/rev/594b98846ce1
(mail: ensure that Python2.4 to 2.7 use the same header format)
msg12688 (view) Author: ThomasAH Date: 2010-05-26.19:29:14
Yes, that's intentional to behave as if two separate repositories had been
used for branching.
msg12683 (view) Author: jglick Date: 2010-05-26.17:55:47
I have tested 1.5.3+51-0d09f2244805 a bit and so far it seems to work.

One thing that was slightly surprising to me is that even 1.5.3 lets you
push (without --force or anything else) a new topological head if the branch
(default or otherwise) previously existed but all its heads had been merged
into other branches. I suppose that is intentional?
msg12654 (view) Author: ThomasAH Date: 2010-05-24.08:32:02
With your example I get
abort: push creates new remote heads on branch 'default'!
too, and on a second look it seems your code is correct:

My example repository:

o  changeset:   5:900f325c69b4
|  tag:         tip
|  parent:      0:09c48accfa5e
|  user:        Thomas Arendsen Hein <thomas@intevation.de>
|  date:        Mon May 24 08:06:50 2010 +0200
|  summary:     bar-3
|
| o  changeset:   4:5ada4f2adb2f
| |  branch:      bar
| |  parent:      1:2a0d9d5a87aa
| |  user:        Thomas Arendsen Hein <thomas@intevation.de>
| |  date:        Mon May 24 08:05:26 2010 +0200
| |  summary:     bar-2
| |
| | o  changeset:   3:553e43fb8afd
| |/   branch:      bar
| |    parent:      1:2a0d9d5a87aa
| |    user:        Thomas Arendsen Hein <thomas@intevation.de>
| |    date:        Mon May 24 08:05:15 2010 +0200
| |    summary:     bar-1
| |
+---o  changeset:   2:3d6d3063866f
| |    branch:      jkfdhdjk
| |    parent:      0:09c48accfa5e
| |    user:        Thomas Arendsen Hein <thomas@intevation.de>
| |    date:        Mon May 24 08:03:49 2010 +0200
| |    summary:     gkjhdfjkghdfjk
| |
| o  changeset:   1:2a0d9d5a87aa
|/   branch:      bar
|    user:        Thomas Arendsen Hein <thomas@intevation.de>
|    date:        Mon May 24 08:01:35 2010 +0200
|    summary:     bar
|
@  changeset:   0:09c48accfa5e
   user:        Thomas Arendsen Hein <thomas@intevation.de>
   date:        Mon May 24 08:01:13 2010 +0200
   summary:     foo


The target only contains revision 0, so 'default' has no new head.
I was confused by the fact that tip created a new topological head.

Additionally I noticed that the default behavior of push without named
branches to an empty repository allows pushing multiple heads, too, so this
is a feature, not a bug :)

With that knowledge I tested:

$ hg push -r 3
abort: push creates new remote branches: bar!
(use 'hg push --new-branch' to create new remote branches)
$ hg push -r 3 --new-branch
added 2 changesets with 2 changes to 1 files
$ hg push
abort: push creates new remote branches: jkfdhdjk!
(use 'hg push --new-branch' to create new remote branches)
$ hg push --new-branch
abort: push creates new remote heads on branch 'bar'!
(did you forget to merge? use push -f to force)
$ hg push -f
added 3 changesets with 2 changes to 1 files (+3 heads)

Looks good to me, just needs tests for -f allowing pushing new branches and
--new-branch aborting when trying to create new heads for branches that
already exist in the target (if not already present in test-push-warn)
msg12653 (view) Author: hstuart Date: 2010-05-24.06:36:32
@ThomasAH: I fail to replicate pushing multiple heads on a different branch
with --new-branch in a simple scenario such as this:

hg init foo
cd foo
echo a > a
hg ci -Am a
cd ..

hg clone foo bar
cd bar
echo b > a
hg ci -m b
hg up 0
echo c > a
hg ci -m c
hg up 0
hg branch foo
echo d > a
hg ci -m d
hg push --new-branch

Can you give more complete reproduction details, thanks.
msg12652 (view) Author: ThomasAH Date: 2010-05-24.06:20:00
I tested with ebc90fd4ebc0 and have some comments/questions:

Sune, Henrik:
- hg push --new-branch allows not only creating new remote named branches,
  but also allows creating new heads in any branch (including default, new
  branches and existing branches) without using --force.
  I think this is a bug.

- hg push -f still works (good), but as it should continue working it should
  again be included in the test-push-warn
msg12651 (view) Author: ThomasAH Date: 2010-05-24.05:59:53
fixed by e43c23d189a5 (push --new-branch) in main/crew

Jesse, does this work for you?
msg11984 (view) Author: jglick Date: 2010-03-09.19:08:20
No. The error message is slightly different in 1.5:


$ hg glog
@  changeset:   2:210f7c37d51d
|  branch:      b
|  parent:      0:422f8cf0cdf4
|  (edited down)
|
| o  changeset:   1:00faa8d2523f
|/
|
o  changeset:   0:422f8cf0cdf4

$ hg out dupe
comparing with dupe
searching for changes
changeset:   2:210f7c37d51d
branch:      b
parent:      0:422f8cf0cdf4

$ hg push dupe
pushing to dupe
searching for changes
abort: push creates new remote branches: b!
(use 'hg push -f' to force)


but the behavior is the same. Even using the new --branch option does not help:


$ hg push -b b dupe
pushing to dupe
searching for changes
abort: push creates new remote branches: b!
(use 'hg push -f' to force)


You still need to use --force:


$ hg push -f dupe
pushing to dupe
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 0 changes to 0 files (+1 heads)


My personal workaround for this bug:

[defaults]
push = -f

and make sure that public servers use a pretxnchangegroup hook:

from mercurial import ui
from mercurial.i18n import gettext as _
def forbid_multiple_heads(ui, repo, hooktype, node, **kwargs):
    violators = [branch for (branch,heads) in repo.branchmap().iteritems()
                 if len(heads) > 1]
    if violators:
        ui.warn(_('Trying to push more than one head to %s; '
                  'did you forget to merge?\n') % violators)
        return True
msg11689 (view) Author: ThomasAH Date: 2010-02-12.16:24:33
http://mercurial.selenic.com/wiki/1.5sprint/Results says:

Things that got done:
 * named branches: heads changes, push/pull/in/out per branch, better error
messages

So is this issue solved for you with current main or crew?
msg11403 (view) Author: jglick Date: 2010-01-07.15:41:49
Issue736 is marked "resolved", but it isn't really. If pushing would result
in a new head, but this is only an incidental consequence of the new
changeset(s) being on a named branch which is otherwise nonexistent or
merged in the remote repo, then Mercurial 1.4.2 prints

  abort: push creates new remote branch '<branchname>'!
  (did you forget to merge? use push -f to force)

This is better than a generic message about multiple heads, but it is not
satisfactory. Using --force is undesirable here: (1) a shell script pushing
changesets cannot trivially tell whether an additional head would be created
in some branch, and thus whether --force might have unintended consequences;
(2) even if called interactively (after receiving the above error message),
there is a possible race condition in case someone else pushes new heads on
the same branch as you, leading to an unusable state of the remote repo
(until someone cleans it up with a merge).

(1) can be worked around by having a script grep for 'push creates new
remote branch' in stderr and retry with --force. (2) cannot be worked around
to my knowledge.

msg9469, msg8026, msg10596, and many other comments confirm that the current
behavior is troublesome to users.

It seems that if the new remote head happens to be on the default branch (if
the remote repo had merged default into a named branch and you are pushing
new default changesets), a different message is printed:

  searching for changes
  note: unsynced remote changes!
  adding ...
  added ... (+1 heads)

I am not sure if there is a reason for the apparently inconsistent behavior.

Suggest either that (a) there be a separate option to push (--branch,
--newbranch, --safe-force, ...) which would permit a new head so long as
this does not result in multiple heads on the same branch; or (b) that this
behavior be the default, i.e. no special option be required to push a new
branch. My preference would be for (b) since I cannot see any danger in
pushing a new or resurrected branch.
History
Date User Action Args
2010-07-13 15:44:58jglicksetstatus: chatting -> resolved
nosy: ThomasAH, jglick, mg, abuehl, tuukka, cyanite, marcusl, Pike, hstuart, jan1972, hgbot
messages: + msg13094
2010-07-13 15:14:46marcuslsetstatus: resolved -> chatting
nosy: ThomasAH, jglick, mg, abuehl, tuukka, cyanite, marcusl, Pike, hstuart, jan1972, hgbot
messages: + msg13093
2010-07-13 15:06:15jglicksetstatus: testing -> resolved
nosy: ThomasAH, jglick, mg, abuehl, tuukka, cyanite, marcusl, Pike, hstuart, jan1972, hgbot
messages: + msg13092
2010-07-13 15:00:06hgbotsetstatus: resolved -> testing
nosy: + hgbot
messages: + msg13089
2010-05-26 19:29:14ThomasAHsetstatus: testing -> resolved
nosy: ThomasAH, jglick, mg, abuehl, tuukka, cyanite, marcusl, Pike, hstuart, jan1972
messages: + msg12688
2010-05-26 17:55:47jglicksetnosy: ThomasAH, jglick, mg, abuehl, tuukka, cyanite, marcusl, Pike, hstuart, jan1972
messages: + msg12683
2010-05-24 08:32:02ThomasAHsetstatus: in-progress -> testing
nosy: ThomasAH, jglick, mg, abuehl, tuukka, cyanite, marcusl, Pike, hstuart, jan1972
messages: + msg12654
2010-05-24 06:36:32hstuartsetnosy: ThomasAH, jglick, mg, abuehl, tuukka, cyanite, marcusl, Pike, hstuart, jan1972
messages: + msg12653
2010-05-24 06:20:00ThomasAHsetstatus: testing -> in-progress
assignedto: jglick -> cyanite
messages: + msg12652
nosy: ThomasAH, jglick, mg, abuehl, tuukka, cyanite, marcusl, Pike, hstuart, jan1972
2010-05-24 05:59:53ThomasAHsetstatus: chatting -> testing
nosy: + cyanite, hstuart
messages: + msg12651
2010-05-07 15:30:36mgsetnosy: + mg
2010-03-09 19:08:20jglicksetstatus: testing -> chatting
nosy: ThomasAH, jglick, abuehl, tuukka, marcusl, Pike, jan1972
messages: + msg11984
2010-02-12 16:24:33ThomasAHsetstatus: unread -> testing
assignedto: jglick
messages: + msg11689
nosy: ThomasAH, jglick, abuehl, tuukka, marcusl, Pike, jan1972
2010-01-21 10:26:53ThomasAHsetnosy: + ThomasAH
2010-01-12 10:19:45jan1972setnosy: + jan1972
2010-01-07 23:06:12tuukkasetnosy: + tuukka
2010-01-07 16:40:02abuehlsetnosy: + abuehl
2010-01-07 16:00:17Pikesetnosy: + Pike
2010-01-07 15:57:14marcuslsetnosy: + marcusl
2010-01-07 15:41:50jglickcreate