Proper command flow for branching strategy - mercurial

So I have a mercurial repository that is the "blessed" repository that I will have open release cycle branches, for example Release1, Release2 etc.
When a dev is working on a release cycle they will pull down Release1, then on their local machine branch for Bug1, Bug2 and fix those.
What command sequence needs to happen for the devs to correctly close their Bug branches, merge the changes into the Release1 branch so that when the changes are pushed to the server no branch information about Bug1, Bug2 etc will be pushed to the server?

If you're using named branches the branch information about bug1 will always be pushed to the server. Named branch names are parts of their changesets and never go away or get changed. You can cause them to not show up in default branch lists by using the --close-branch option to commit, but they're still there and listable.
If you want a branching model where the branch names don't escape Mercurial provides some other branch options that may suit your needs better:
http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/
If someone suggests using the 'TransplantExtension' to merge the branches in and hide the branch information, don't listen -- it's a terrible idea.

Related

Can't push new heads - fail to see how they would be created

I'm fairly new to version control in teams. So far I've mostly used it solo.
I've read that the following workflow is recommended:
Commit locally, pull master, merge master into my branch, merge my
branch into master, push. Several times a week or even day
So that's what I tried to do. However, when I was done with my feature, and tried to push, tortoise hg told me, that this would create new remote heads.
hg help push tells me about two options:
Merge first: Did that
Use -f: I know enough not to do that.
I think I understand the concept of rebasing - which I don't think applies here, since I'm the only one who did anything in this commit tree. Of course I've pulled.
So my question is: How can I resolve this specific situation?
Also, recommendations for where to learn proper version control workflow would be nice. Everything I find tells me what the commands are, but I've failed to find clear instructions on when to use them.
I've added a picture of the project. Commit 147 was mine, and I could push it just fine. All oher commits are also made by me.
hg reports a "head" for every named branch. In your screenshot, you are needing to push rev 154, which is the head of your kjeld branch. It is an outgoing changeset because you are pushing rev 155 and you must therefore push 155's entire history as well. Others will get that branch when they pull your changes and will have a head on their version of kjeld (note that it will most likely not be numbered 154 since those numbers are repo specific). You will be fine though since that head is a close-branch changeset so it will not appear in their default list for hg heads and hg branches.
One way to avoid your current issue is to use bookmarks to temporarily note what that head represents e.g. issue-45, big-feature-2, etc. and only push when merged into mainline development.
For us, we set up a "private" repo for each dev on the server where they store/backup work in progress. It is expected that there are multiple heads, dead branches, and other gunk in these "private" repos. The dev repo, however, only ever has a single head and must pass the build and build tests.
In response to your comment about your "private" branch: When you push your tip you will also push your branch named kjeld. Others who want to work on that code must pull it to get the tip of your development. It will not be a "private" branch.

TortoiseHG merging local into branch head

I have a repo in TortoiseHG with a single branch (next version development), but modifications to the local (bug fixes)... something like...
Local 0-------3--4
\
Branch 1--2
I want to do some more development on the branch version but with the subsequent Local changes merged into it. And I want to leave the local version in a state where I can continue development without the branch changed.
I'm not sure if what I'm asking is actually possible, or whether coming from a Visual SourceSafe environment is just clouding my ability to see something that should be obvious.
In fact, thinking about it a bit more (as I was writing the above) I'm wondering if my approach is the wrong way around. I should probably have continued with the future development in the local version and then create a bug-fix branch that I could have merged back into local one.
So the question is, is there a way to get around what I want to do with the current repo setup, or should I export the individual revisions and rebuild the repo from scratch? (Or any other options?)
This seems like pretty normal Mercurial handling to me.
You have:
Two branches
Want to make sure one of the two branches have all the updates of the other
Want to make sure that other branch does not have any of the updates from the first (yet)
You basically just have to merge the Local branch into the Branch branch at regular intervals, but not the other way around.
Whenever you merge to a branch, you first update to the head of that branch. This makes the changeset you commit to persist that merge be on that branch as well.
In other words, you would do this:
Update to the head of Branch
Right-click on the head of Local and select "Merge with local..." and go through with the merge
Commit, this new changeset ends up being on the Branch branch
The Local branch is still blissfully unaware of the changes on the Branch branch.

Mercurial merge / remove a feature branch

I am trying to work out how to use the Branch-per-feature approach in mercurial but having created a branch to work in, and merged it back to default, am unable to push my changes back up to my master repository. What is best to do?
I created a branch "Gauge customisation", did some work in that branch and then merged it back into the default. Carried on with a few more changes in default and now I want to commit this back to my master repository. But when I try I get:
abort: push creates new remote branches: Gauge customisation!
hint: use 'hg push --new-branch' to create new remote branches
I didn't think the branching would show up in the master repo and that by merging it locally I could somehow work in the branch (or potentially branches) and then when I've tested everything, push it up to the master repo.
Should the Gauge customisation branch still show up? Really I thought I'd only see default at this stage? But is that me not understanding the tools properly? Should I be creating the remote branch?
Ideally I'd like to be able to open a branch per feature and have 3 or 4 such branches running at any one time (it's the way my company works) so I'd like to get a solid grasp of things now.
Technically you could just commit the new branch to the master repo using --new-branch. As displayed in your screenshot, there is not really a new branch with a head from a topological view, but from a namespace view, i.e. when hg aborts your push, it just wants your explicit acknowledgement to add a new branch (name) to the remote repo.
However, for tasks like your's -- temporary feature branches -- a more common workflow is to not use named branches but anonymous/bookmarked branches or separate clones. Named branches usually are used for long-living branches like stable, legacy, and so on. If you create an anonymous/bookmarked branch and merge it back when its feature is finished, hg won't complain when pushing.
An often recommended reading in that context is A Guide to Branching in Mercurial.
Merging two branches does not get rid of either of them. You will need to close your feature branch manually by switching to it and doing:
hg commit --close-branch -m 'Closing branch'

Mercurial push problem

I've just got a problem with hg push command. What I did - Firstly I created 2 branches hot-fix-1 and hot-fix-2 made some changes in each branche, merged it back to default and closed those branches with the command:
hg commit --close-branch
If I start hg branches I have the following output:
default 29:e62a2c57b17c
hg branches -c gives me:
default 29:e62a2c57b17c
hot-fix-2 27:42f7bf715392 (closed)
hot-fix-1 26:dd98f50934b0 (closed)
Thus hot-fix-* branches seems to be closed. However if I try to push the changes I have the next error message:
pushing to /Users/user1/projects/mercurial/mytag
searching for changes
abort: push creates new remote branches: hot-fix-1, hot-fix-2!
(use 'hg push --new-branch' to create new remote branches)
and it does not matter which command I use hg push -b . or hg push -b default
So the question is how I can push those changes to repository without creating new branches.
P.S I used to work with git and was hoping that similar branching model can be used in Mercurial. Thanks
First, as many others have pointed out, using a named branch for short lived work is not a recommended practice. Named branches are predominantly for long lived features, or for release management.
Given that you are in this situation, there are a few options available. All of them involve modifying history (as you're obviously trying to change something you've done).
One is to just push the branches as is, learn from the experience, and move on. If the rest of the team is fine with this, then it's a case of adding --new-branch to your push command.
If the rest of the team, or you, really want the history to be clean, then you'll need to dig deeper.
If you aren't pushing, then definitely make a clone of your current repo. This way you have a copy of the original work to fall back on.
I see 2 main approaches here. Strip off the merges and rebase your branches onto default. This will get rid of the named branches or graft/transplant your changes. Both will be the same end result, but the implementation is slightly different.
If you merely want to use graft, that is now a built-in function starting with HG 2.0. It replaces the transplant plugin, and is much nicer to work with as it uses your usual merge tool if there are conflicts.
To use it, update to the default branch. Then, use the command:
hg graft -D "2085::2093 and not 2091"
the string after -D is an hg revision selection query. In your case, you'd likely only need '{start}::{end}' where start is the changeset at the start of the branch, and end is the end changeset of the branch (ignoring the merge).
If you did several merges, you'd have to pick and choose the changesets more precisely.
The other option is to strip the final merges, and use the rebase command that is part of the mq plugin.
You'll have to strip your merge changesets to get rid of them, and then update to the tip of the branch you want to keep. Select the start of the first named branch, and do a rebase. This will change the parentage of the branch (if you're familiar with Git, then this is very much like it's rebase).
Then repeat for the second branch. You should now have one long branch with the name default.
Just do the:
hg push --new-branch
It will send over those branches, but they'll be closed on the receiving end too, so no one should be bothered.
See my comment on the question for why Named Branches are best saved for long-lived entities like 'stable' and anonymous branches, bookmarks, or clones are more suitable for short lived things like hot-fixes and new features.
Your hot-fix changes were made on branches. Regardless of whether the branch is active or closed, it does exist.
To push the changes to the server (without rewriting history), you must use the --new-branch option (e.g. hg push --new-branch`).
Since you merged the branches into default, there will still only be one head (as you have already seen in your local repo).
If you really can't live with pushing the branches to the server, then you must rewrite your local history as suggested in Mikezx6r's answer.
In addition to the methods he mentioned, you can also import the changesets into a patch queue and apply them to the tip of your default.

Bad idea to force creation of Mercurial remote heads (ie. branches)?

I am developing a centralized web application, and I have a centralized Mercurial repository.
Locally I created a branch in my repository
hg branch my_branch
I then made some changes and committed. Then when I try to push, I get
abort: push creates new remote branch 'my_branch'!
(did you forget to merge? use push -f to force)
I've just been using push -f. Is this bad? I WANT multiple branches in my central, remote repository, as I want to 1) back up my work and 2) allow other developers to develop with me on that branch.
Is it bad or something to have branches in my remote repository or something? Should I not be doing push -f (and if not, what should I do?)? Why does Joel say this in his tutorial:
(source: grabby.info)
Occasionally I've made a change in a branch, pushed, switched to another branch, and changes I had made in that branch I switch to were mysteriously reverted to a previous version from several commits ago. Maybe this is a symptom of forcing a push?
My suspicion is that others with more time can answer better, but here is something related I found:
https://www.mercurial-scm.org/wiki/TipsAndTricks#Prevent_a_push_that_would_create_multiple_heads
It is related to a different option (specifically breaking push -f), but it mentions something along the lines of what you ask:
While a plain 'hg push' will warn you if you're going to create new heads, that is merely a warning on the client side intended to help/remind users that they may have forgotten to merge first.
Assuming this is an accurate statement then you are perfectly safe to do so.
Note however that I have only basic knowledge in Mercurial so shouldn't be used as a source of complete truth :).
No, it's not bad to force the push when you create a new branch. The error/warning is issued because the new branch causes the repository to have two topological heads. That is, there are now two changesets without children: the tip of your default branch, and the tip of your new branch.
With Mercurial 1.6 (to be released in two weeks time) you will be able to do
hg push --new-branch
to allow the creation of new remote branches. This is safer since --force disables all safety guards, whereas --new-branch only allows you to create a new branch.