The use of local branches
Heavy new stuff may take quite a long time to be stable and mature enough to be shared even with other developpers. Mercurial, as a distributed SCM, allows to keep a fine-grain history through local commits without letting the genie out of the bottle. It is only through merging and pushing the new changesets to some common repository that new things gets available to others. Yet it is quite frequent that one would like to work on heavy stuff while maintaining the ability to perform fixes and smaller task on the trunk, without releasing into the open experimental and unfinished changesets. With mercurial, there are two natural answers to this problem : cloning and branching.
Making a new clone and working the heavy stuff in it is probably the simplest way: things get naturally separated since they happen in distinct folders. However, maintaining and building multiple clones may prove to be quite demanding, in terms of physical spaces and working folder organization. In this short article, we will investigate the other option: branching. We will demonstrate how to :
- Start a new local branch,
- Work in it,
- Switch to the trunk and back,
- Close the branch if it appears to be a dead-end,
- Merge the branch with the trunk when it is ready.
Creating a new branch and working in it
The first step toward local branching is to create a new branch, which can be done by using:
hg branch new_heavy_feature
This creates a new branch called new_heavy_feature and switch to it.
To check on which branch the repository currently is, simply run:
$ hg branch new_heavy_feature
We can now start working and make commits, as usual:
$ hg commit -m "ENH: my new changeset"
To see all available branches, you may run:
$ hg branches new_heavy_feature 16326:d499e4b4fd6c default 16325:e1932b72ca58 (inactive)
Note that the default branch is the trunk (and currently marked inactive). Also note that a branch with no changesets in it will not appear here.
Switching to trunk and back
To switch back to the trunk, simply run:
$ hg update default 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
You are now working on the trunk version shared with everybody. You can commit, pull --rebase and push without sharing the changesets you made in your new_heavy_feature branch.
Careful: if you simply run
$ hg push
You will get the following error:
searching for changes abandon : push creates new remote branches: new_heavy_feature! (use 'hg push --new-branch' to create new remote branches)
Do not try to force pushing (using the -f option or --new-branch)! In OTB it is forbidden to push new remote branches (actually this may even be forbidden on the server side). To push your changesets made to the trunk, you need to specify the head you want to push. The topmost head of the trunk is the one with no branch properties:
$ hg heads changeset: 16326:d499e4b4fd6c branch: new_heavy_feature tag: tip user: <> date: Thu Oct 31 14:35:06 2013 +0100 summary: ENH: New commit in new_heavy_feature branch changeset: 16325:e1932b72ca58 user: <> date: Thu Oct 10 17:01:28 2013 +0200 summary: ENH: Some trunk commit
You therefore need to specify the correct changeset short (or long) id to push:
$ hg push -r 16325
Last, you can switch back to your local branch running:
$ hg update new_heavy_feature
Work done: merging with trunk
Once the work on the local branch is completed and you want to share it with others, you can rebase your branched changesets on trunk. If you need to, you ensure you are on the trunk and rebase incoming changeset:
$ hg update default $ hg pull --rebase
Now, track the head of the local branch you want to rebase :
$ hg heads changeset: 16326:d499e4b4fd6c branch: new_heavy_feature user: <> date: Thu Oct 31 14:35:06 2013 +0100 summary: ENH: New commit in new_heavy_feature branch changeset: 16325:e1932b72ca58 tag: tip user: <> date: Thu Oct 10 17:01:28 2013 +0200 summary: ENH: Some trunk commit
And rebase the commits of your local branch onto trunk using the -b option and the id of the head of you local branch:
$ hg rebase -b 16326
Now, the local branch you created is no longer visible:
$ hg branches default 16442:518c25a95e45
And you can safely push to trunk.
Dead-end: closing branch
If your work reaches a dead-end, you can get rid of the local branch you created by closing it:
$ hg update new_heavy_feature $ hg commit --close-branch -m "Closing dead-end" $ hg update default
The branch will no longer appear in hg branches. However, it is still there, and you can still swith to it using hg update.