A little while ago I wrote a quick start guide to branching in Mercurial and, as is normally the case when you don’t actively follow development, Mercurial 1.5 has been released with a lovely new feature which impacts working with branches. 

My biggest annoyance when working with branches is by default all branches are pushed/pulled to the remote repository.  When in reality, I often want to just push the branch I’m currently on.  Mercurial addressed this by adding a branch only option to Push, Pull, Clone, Incoming and Outgoing.  To use the branch only option you append –b to the command followed by the branch name, for example:

hg push -b default

This will only push the default branch back to where the repository was cloned from (You can still specify a location to push to if required.)  This works exactly the same for all the other commands.

A handy shortcut to push the current branch is use ‘.’ as the branch name:

-b .

This will perform the command only to the branch you’re currently on.  Since I tend to push more than I do most of the others, I have set up an alias to map push current branch to pc.  You can do this by adding a section to your hgrc like:

[alias]
pc = push -b .

Branching Without Having It In Your History

Cloning locally has always been an option to create a branch or fork of the code that is still linked to the original code base, IE you can push and pull to it, but it doesn’t become part of your history in the other repo unless you pushed it back.  But I’ve never liked it because it takes a copy of everything and sets the current branch to the default branch.  Trivial, maybe, but not something I found desirable.

The new branch options makes cloning locally a lot more attractive to me.  It means I can just clone a branch, make a quick change or two and either merge it back in or delete the directory and pretend I never had that idea!

Powershell and Mercurial

As part of my continuous improvement I’ve been learning PowerShell.  One way I’ve done this is by replacing all my cmd.exe usage with the PowerShell prompt instead.  This led me to discover an excellent cmd-let (script or whatever the proper name is, I’m still learning :) ) to display the name of the current branch and status of it when you’re in a Mercurial repository.  It looks like:

Powershell Status Display More information can be found about this here.

, , ,

I’m a recent convert to the ways of the DVCS and my chosen flavour is Mercurial.  There is tons of documentation out there but I couldn’t find a “Quick Start for Half Wits to Branching” that appealed to my simple nature.  So I thought I’d have a go at writing one based around my current workflow.

Mercurial has several ways to work with branches but I find named branches best suit my feature branch approach to using SCM.  There is an excellent guide to all the types with their advantages and disadvantages, here.

I’m going to assume you’re familiar with basic push, pull, and commits.

Creating and Moving Between Named Branches

To create a new named branch you simply enter:

hg branch "<branch name>"

This will mark the current working revision with the branch name you specified but it will not be part of your repository till you next do a commit.  When committing it will create the branch and add all the changes since your last commit.  This is quite a big gotcha, if you want to any changes to be committed on the old branch before moving to the new one you must do a commit before branching.

Finding out the name of the branch you are on is be done by entering:

hg branch

You can list all of the branches that are currently open by using:

hg branches

This outputs a list of branches with the changeset number that is the head of the branch, for example:

hgbranches2The ‘default’  branch is setup when the repository is first created and is the equivalent of a mainline or trunk branch.

To move between the branches you do an update with the name of the branch in.  This will fail if you have any uncommitted changes but you can force it to update and lose any the changes by using –C.

This will just move between branches:

hg up "<branch name>"

This moves between branches losing any changes:

hg up -C "<branch name>"

The following examples ties a few of these together and shows how creating a branch without committing first moves any recent changes into the new branch.

sample1

Merging

Merging two branches is done by updating to the branch you want to be the target then merge in the changes from the source branch by specifying its name. For example if you wanted to merge the latest edits from default into the feature branch named “Feature X” you would do:

hg up "Feature X"
hg merge “default” 

 

It will attempt to merge the changes without any user intervention but if it can’t it will ask the user to do it.  On Windows, KDiff3 is installed along with Mercuiral and is used to merge changes.  Again none of these changes will be saved until you commit.  If you regularly work on a feature branch while others update the default branch, I would strongly urge you regularly merge updates from the default branch to stop you having one almighty nightmare merge at the end.

Merging offers a preview option by passing –p to the merge command.  This allows you to see upfront if there will be any conflicts or problems, I find this quite useful when assessing how long a merge will take. 

Pushing 

Mercurial by default pushes your whole repository, including all your local branches, to the remote repository.  It works exactly the same if the branch (or branches) exists in the remote repository.  If they don’t it will fail and you can use the –f option when pushing to force it to create the branches on the remote repository.

But sometimes you want to just push changes on the current branch, leaving the others behind.  I’ve recently discovered a great tip for doing this, you can just push the current revision with its associated history and parent by using:

hg  push --rev .

The ‘.’ is a shortcut for the most recent changeset on the branch and it will only push changes on that branch.  This, of course, means that the branch must exist or be created on the parent.

Closing

Mercurial doesn’t support the deleting of branches (at least that I’ve come across) but you can close a branch.  Closing a branch is done by selecting the branch and doing a commit with the close flag, for example:

hg up "<branch to close>"
hg commit --close-branch

This marks the branch as inactive and stops it appearing when you list the branches using hg branches.  It is possible to still see all branches including closed ones using the this command

hg branches -c

One major downside is, closing a branch does not prevent it from being pushed.  This means you will still have to create it on the server or just push the current changeset as shown above.

, ,