7
votes

I've created a named branch in mercurial, committed some changes, and now I want to push that back to the central repo. I've done a fetch, verified I have no changes to merge, but when I try to do the push, I'm getting the message push creates new remote head but I don't understand why. I'm the only dev on this branch and it is still local to my repository.

>hg fetch (pull/update/merge)
>hg status (shows nothing)
>hg push --new-branch mybranch
 searching for changes
 new remote heads on branch 'default'
 new remote head c3064f3cf1b7
 abort: push creates new remote head c3064f3cf1b7!
 (did you forget to merge? use push -f to force)

Any ideas?

Edit: sorry for any confusion, this is a named branch created by hg branch mybranch

Update: using hg heads yields multiple heads all on different branches. I have one for my branch, and one under default:

changeset:   515:97b9a7802751
branch:      mybranch
user:        me <[email protected]>
date:        Mon Feb 27 13:21:54 2012 -0800
files:       CryptoRandom.cs
description:
fixing error message for size of max


changeset:   504:c3064f3cf1b7
user:        me <[email protected]>
date:        Thu Feb 09 11:41:32 2012 -0800
files:       CipherKey.cs
description:
removing ambiguous characters - CAC-47

using hg log -r c3064f3cf1b7 yields the following (this is the head on default):

changeset:   504:c3064f3cf1b7
user:        me <[email protected]>
date:        Thu Feb 09 11:41:32 2012 -0800
files:       CipherKey.cs
description:
removing ambiguous characters - CAC-47
2
hg heads will show you all heads. That ought to tell you where c3064f3cf1b7 stands with other heads, too.Joel B Fant
Folow-up to @JoelBFant: hg log -r c3064f3cf1b7. It seems you have not new named branch, but anonymous branch in defaultLazy Badger
added more info on the branch. I'm pretty sure it's a named branch...earthling
And you've pulled everything for the default branch from the other repo that you wanted to push to?Joel B Fant
I'm not working on default and not ready to merge back yet. Do I really need to switch to default and pull?earthling

2 Answers

14
votes

The confusing is that the --new-branch flag has no effect when pushing feature branches (also known as anynomous branches). An anonymous branch looks like this:

... [a] --- [b] --- [c] <- the servers head on default
               \
                [x] --- [y] <- my feature branch on default

All changesets are on default so you now have two heads on default. When you push, you will create two heads on the server — but Mercurial aborts before that with the warning you see. It aborts since having multiple heads on a server is confusing: when you hg clone your working copy will be updated to one of them, almost at random.

The --new-branch flag is only for named branches. Mercurial will normally abort if you push a new named branch to a remote repository. Adding the --new-branch flag is how you tell it to go ahead.

Unfortunately, we don't have a dedicated --create-new-feature-branch flag. We only have the --force flag which tells Mercurial to go ahead and create the two heads in the remote repository. The downside of --force is that it overrules all safety checks: you can push three or more new heads with that flag and you can even push into an unrelated repository. So you should use hg outgoing to double check what you're going to push.

I wrote above that multiple heads on the server is confusing since a new clone will be updated to a random head. To avoid the confusion you can give the feature branches names by bookmarking them. You will still be updated to a random head, but hg bookmarks will show you the available feature branches and you can then update to the right one. So if you're using such a workflow, then go ahead with hg push -f.

1
votes

Just magically resolved this, yet still not clear why. It does seem to be a problem with default even though I'm not working on that branch. I could call >hg branch and get the expected branch name.

I had a change in my local default branch that was not pushed, and did not want. I backed out of that change and then committed. I then did a fetch on the default branch and merged that to my feature branch. Then back on default I merged with the changeset on default that I backed out of I believe. At some point during that process I got yet another head, which probably caused the multiple merges.

It all seems to boil down to existing heads on default, but I still do not know why (or why we would want to) that affects a separate named branch.

This all seem overly complicated for what I expect to happen (and what everyone can simply draw out in ascii diagrams)

Edit

It looks like the problem stemmed during the initial branch perhaps. It looks like I branched twice and [j] is an anonymous branch on default.

to sort of visualize what seems to be going on [j] is my changeset I backed out of and [k] is my first commit on mybranch:

[a] -- [b] -- [c] -- [d] -- [e]  (default)
         \             \    /
          [j]-----------\---     (not sure where this branch came from)
            \            \
            [k] -- [l] -- [m]    (mybranch. Still separate from default)