In a project, I have a default branch and another named branch. After a merging both branches and committing it, the graph in TortoiseHg shows that both branches have been merged. However, pushing to a remote repository (which is at the stage before branching, it only has the default branch), I get the message "abort: push creates new remote branches".
If I'm not mistaken, I'm left with one branch after merging, so why this error message? Note: the graph still shows that I have 2 heads, is it in anyway related to this?
You're getting that error message because the named branch -- and all its changesets -- still exists in your local repository: you've merged the changes into the default branch, that's all.
You see two heads because you're using a named branch: from the help text for hg heads (the command line equivalent of selecting Heads in the repository explorer):
Branch heads are changesets that have no child changeset on the same branch.
Since you have two branches in your local repository (default and the named branch), you have two heads by definition.
To resolve the error message that you're getting, in the repository explorer, there's a Push New Branch option at the bottom of the Synchronize menu; select it, then you should be able to push to the remote repository.
Related
In my local fork of the upstream Mercurial repository I have multiple branches. Prior to beginning work on one of the outdated branches feature I would like to obtain all the changes from the local default branch. How do I do that? When I execute:
hg up feature
hg merge default
I obtain an error message:
abort: merging with a working directory ancestor has no effect
I would like to obtain all the changes from the local default branch.
I would do a hg pull first.
Then hg up feature, to switch to such branch in case you are on another branch.
Then bring default changes into feature by doing hg merge default
abort: merging with a working directory ancestor has no effect
Such message indicates that the parent of the current revision at feature is the latest revision (or tip) in default in your working copy.
I am trying to do something very simple: create a new branch. But I messed up. Where did I make the mistake, and how do I fix it?
I am the only user of Mercurial. I had revision 54 committed and pushed to remote repository. I wanted to create a branch based on revision 53, so I updated my local copy to revision 53, made changes, and committed (ignoring the warning about "it's not the head"). Then when I am trying to push to remote repository, it says
abort: push creates new remote head
Maybe I needed to tell Mercurial that I want to create a new branch? If so, how and at what point?
Thanks!
You tell Mercurial that it can go ahead with
$ hg push --force
You need to force it since multiple (unnamed) heads are normally discouraged. The problem with them is that people that clone the repository wont know which one to use. But since you're the only user you can just go ahead and push.
The alternative is to use a named branch (with hg branch) and then you'll use
$ hg push --new-branch
to allow the creation of a new branch on the remote. Named branches have the advantage that they make it easy to distinguish the two branches. They have the disadvantage that they are permanent. Permanent means that you cannot remove the branch name from the changesets on the branch — the name is literally baked directly into the changeset.
Bookmarks provide a way to have non-permanent branch names, see hg help bookmarks.
Another reason for this error: probably there are some UNMERGED changes form the central repo in your default branch.
hg up default
hg merge
hg ci -m "Merge"
hg pus
I did this. Using TortoiseHg ... this is how I fixed it:
In settings, I enabled the Strip extension then right clicked the branch i did not want, Modified History - strip. If you have pushed, then it needs to be stripped from all other repositories, including workmates who have pulled your unwanted branch.
An alternative is to merge the unwanted branch into your main branch, but do not take any of the changes from that branch - I am unsure of how that mechanism works.
Isn't this a normal workflow?
[default] $ hg branch foo
[foo] $ [... some commits ...]
[foo] $ hg update default
[default] $ hg merge foo
[default] $ hg commit -m "merged foo"
[default] $ hg push
abort: push creates new remote branches: foo!
(use 'hg push --new-branch' to create new remote branches)
What is the otherwise ideal way to do branching → merging → pushing?
The mercurial philosophy is that you should not be pushing things which make it harder for other users of the repository. Relevant to this question is that multiple heads make it harder for other developers, since they would then need to merge your changes. Hence by default pushing new heads is rejected by the server. The -f option was used to allow pushing new heads.
However, the case of pushing a new named branch is quite different conceptually to pushing a new head on the same branch. Many workflows (including mine) do each task on a separate named branch. The --new-branch option allows you to push up a new branch, whilst rejecting new heads on existing branches. It's also different (as you've seen) because it's needed even if the new branch does not create a new head (due to merging).
My personal feeling is that new branches should be allowed by default, but the mercurial developers prefer otherwise.
This is a one-time thing. Just use --new-branch the first time you push a (new) branch. It's normal.
Every other push can remain as hg push, no --new-branch flag.
That depends on what the branch is used for.
Is it used internally in your own repository clone it would be appropriate to commit your changes to your branch as long as you develop on your feature decoupled from the others.
After you finished you'll have to invest some work to keep track on the efforts of other people who may have done changes on the default branch
Then you should update in their changes, resolve the conflicts commit your part.
Switch over to default and make your feature part of the default branch by merging in your changes. Now you can close your branch, commit the stuff and push it!
branching out -
[default]$ hg branch talks
[talks]$ <... some commits ...>
[talks]$ hg update default
merging back -
[default]$ hg merge talks
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
pushing to remote repo -
[default]$ hg commit -m "merging talks to default"
[default]$ $ hg push
abort: push creates new remote branches: talks!
(use 'hg push --new-branch' to create new remote branches)
Further investigation revealed that remote repo doesn't want me to have multiple heads at the remote end. But I just did a merge to merge the two heads into one, isn't it?
The graph from hg serve also seems to agree with me (I hope)
However, I also see two heads from hg heads
[default]$ hg branches
default 9:85752ecd6326
talks 8:2b00714d76d5 (inactive)
The solution is in the abort message: use 'hg push --new-branch'. You've created a named branch called talks so it needs this extra switch, regardless if you have merged the named branch back to default.
I'm guessing you've misunderstood the branch feature. You've just created a branch who's name will live forever in the repository. I suspect you didn't really want to do this. You might want to investigate the bookmarks feature for local branches that don't end up with names that live forever in the repository.
Mercurial balks at pushes that add new global branch names to the repository being pushed to because that's so very rarely what you really want to do. hg push --new-branch will tell Mercurial that yes, you really mean to do that.
The two heads you're seeing are misleading. Notice how one head is listed as '(inactive)'. That just means it's the last change on the global branch, but not an actual head. You frequently want to see the heads of branches, even if those heads actually have children and are not really heads.
As a small aside... I wrote the code that added that feature to the 'heads' command awhile back. :-)
It seems naming a previously unnamed branch doesn't really work out. It creates a nasty multiple heads problem that I can't find a solution for.
Here is the workflow...
UserA starts working on feature that they expect to be small, so they just start working(off the default branch). The change turns out to be a large project and will need multiple contributors. So UserA issues... hg branch "Feature1" and continues working, committing locally s needed.
UserA then pulls down the changes from the central repo so he can push.
At this point, why does hg heads return 3 heads? It shows 2 for default and 1 for Feature1. The first head for default is the latest change by another user on the branch(irrelevant). The second default head is the commit prior to the hg branch "Feature1" commit.
The central repository has rules enforced so that only 1 head per branch is allowed, so forcing a push isn't an option. The repo doesn't want multiple heads on the default branch.
UserA should be able to push these changes so that other users can see the Feature1 branch and help out. I can't seem to find a way to "correct" this. I don't think I can re-write the branch of the initial commits for the feature, before it was a named branch.
I know the initial changes before the named branch are technically on the default branch, but does that mean they will be heads until that Feature1 branch is merged?
I have found a solution without have to re-clone and merge changes in. I prefer this method mainly for historical purposes as I think it's valuable information on what happened with the feature (aka it started small and then was re-thought to be larger etc..)
In my example, UserA should update to the unwanted head on default and close that branch of default, as it is unwanted. This will leave 2 heads one for default and one for Feature1 as expected.
hg update -r X // X is the rev of the unwanted head.
hg commit --close-branch -m "Moved to Named Branch Feature1, cleaning up initial work"
Then update to the Feature1 branch, push and continue working.
Another workflow is almost the same except the UserA decided to push Feature1 for others to help and default has not been moved forward by anyone else. The local repo only has 2 heads and the user could push, but UserA does NOT want to just push as the tip of default would now be the changeset that really "belongs" to Feature1.
UserA should update to the latest, unwanted changeset of default. Then revert the default back to the revision before UserA starting working.
hg update default
hg revert -r Y // Y is the changeset before UserA started working on the feature
hg commit -m "Reverting changes that now exist in Feature1 branch"
Then update to the Feature1 branch, push and continue working.
The reason you're seeing two heads on the default branch in the local repo is because, after the most recent common ancestor, the changesets in the central repo have nothing in common with the changesets in the local repo.
To solve your problem:
Create a new local clone of the central repo at whatever revision you want (it will probably be easier if you use the most recent common ancestor).
hg clone -r common_ancestor central local2
Export the changes from the first local repo. Note the colon after first_local_change to get all the changes in that repo.
cd local1
hg export -r first_local_change: > ../local1.patch
Go to the new local repository, create the feature branch to import the changes into, then import them:
cd ../local2
hg branch feature
hg import ../local1.patch
hg import has an option to use the branch information in the patch file, but it's disabled by default.
At this point, you can continue using the new local repo in the original one's place. Also, I would double check to make sure that everything is as it should be in the new repo.
We found this to be a very big problem with our team (doing branch-per-feature) and ultimately stopped the hgweb.cgi script working (HTTP 414 Request too Long).
from hg help heads: hg heads with no args will show branch heads, which by definition are changesets that have no children on the same branch. hg heads --topo should give you result you need in this case.
Don't go via the central repository. Just have your developers pull from each other.