Dave's Visual Guide to TortoiseHg and Mercurial's Named Branches
...and using TortoiseHg with Bitbucket
NOTE: This article is old. I still (2018-06-14) love Mercurial and use it every day. But now I'm on a Linux desktop and I use Mercurial at the command line (
hg). I've also found that I don't have as much need for branches as described below. I just use tags for version numbers. You can always branch off of old commits at any time (with a name or not), so pre-creating them like I describe is unnecessary. Mercurial is incredibly flexible, so it may take a while to find the method that works best for you!
An explanation of using named branches in projects with TortoiseHg for Windows and collaborating with others via Bitbucket.
The three sections of this guide (The Basics, Branching, and Bitbucket) are intended to be read separately or in order. This aimed at newbies and I've tried to not assume much prior knowledge. But I don't walk through installation of the software. Nor do I explain more than a small fraction of the capabilities of and terminology used by version control systems like Mercurial. Also, this is Windows-centric, but I imagine it will be a similar experience for Linux and Mac OS users as well.
There are a bewildering number of different ways you can work with Mercurial. This is the way that feels the most natural to me. However, I make no claim that this is the correct (or even a correct) way to use TortoiseHg and Mercurial. I want to keep this article short and to the point, but accuracy is important to me. Please comment below if you find any errors or inaccuracies.
Last updated Feb 26, 2012.
Table of Contents
- The Basics (Creating and Committing Repositories)
The Basics (Creating and Committing Repositories)
Feel free to skip this section if you're already familiar with the basics of TortoiseHg usage.
Creating a new repository
If you don't already have a repository, you'll need to create one. TortoiseHg makes this very easy. Simply right-click in the root of your project's directory (in Windows Explorer) and select TortoiseHg->Create Repository Here.
Then click on the Create button on the next dialog.
Mercurial will generate the repository files such as .hgignore and the .hg directory. Depending on your settings, the files may be hidden.
Here, you can see the new repository files. I have also added a new README file in the root of the project directory. This file will need to be committed before it will exist in the new project.
Making changes and committing
Your repository is an empty shell of a thing until you make some commits. You may make your first commit immediately after creating the new repository, but I often like to create a file or two just to make it worthwhile.
To commit with TortoiseHg, just right-click in the directory and chose Hg Commit.
Since every commit ideally has a purpose, it's very important to give them good descriptions. Since this commit is the first, we'll simply label it as the Initial Commit. Enter your commit message into the message field as pictured and hit the Commit button.
Also be sure to check the checkboxes next to any changed files in the left-hand column that you wish to include in the commit. There are many good reasons to commit only some of the changed files, but for the initial commit, you're likely going to want to commit everything.
TortoiseHg will ask if you're certain you wish to add or remove files during a commit. In this case, we certainly do.Click Add.
Mercurial will now add the changes to our default (main) branch. Our files are now being tracked and we can always retrieve this version of these files. Comforting!
Admiring our new repository
To see what we've done so far, open up the Workbench. To do this, right-click again in your project directory. This time, choose Hg Workbench.
With the Revision Details button selected (it is likely already selected by default - it's the icon with the little person and a document), you can see the list of commits we've made so far. We have only one, our Initial Commit. You can also see that we're in the main branch called "default" and that the Initial Commit is a tip. A tip is simply the most recent revision in the repository. Notice that the Working Directory is also listed above the tip of the branch. It contains any uncommitted changes you may have made in the project directory.
Using just these simple commits, you can start building up a secure history of your source code as it changes over time. If you name your commits well (or even if you don't) you'll be able to find any version you need. Now you don't have to keep commenting out big chunks of old code just to be sure you won't need it anymore or worry that recent changes will break something and you won't be able to get back to a working copy. Liberating!
Having a version history which we can use to rewind to any point in our source code is a powerful thing. It lets us work on files without fear of ruining them. But that's only the tip of the Mercurial iceberg.
Why named branches are handy
Consider the following scenario: you're about to embark upon a new experimental feature. This feature seems like a good idea, but it's a bit of a gamble and you're going to need to see it in action before you're sure it should become a permanent part of the project. To make this feature work, you're going to need to make sweeping changes across the project.
In the meantime, people are using your project and may find bugs which will need fixing. There may even be other developers working on the project at the same time.
Now assume that someone finds a critical bug in your project. The fix is simple, but to do it, you're going to need to make changes to the original versions of the files that existed before you started the new experimental feature. On top of that, you're not going to want to have to keep track of and make the same bug fix to the files again after you launch a new version of the project which incorporates the experimental feature. Ugh!
Mercurial's named branches to the rescue! With a named branch, you can work on the experimental feature and the main branch of the project at the same time and in the same directory. It's based on simple principles, but it's almost magical to watch.
When you're done with the feature, you can merge the branches to update the main branch with the changes in the experimental feature branch even if you've made changes to the main branch!
Creating a new named branch and committing it
Here we can see that the awesome_project directory (which is the root of the Awesome Mercurial Branch Test project) contains two PHP source files and a README file.
Now let's create a new branch called 'risky' in which we can build our new experimental feature. To do this, select the Commit view of the Workbench or right-click in the project directory in Windows Explorer and select Hg Commit. Then, click on the text labeled Branch: default. This will pop open a dialog box. Select Open a new named branch and enter the name of the branch, 'risky' in this case. Then click OK.
Notice that the branch text has changed to New Branch: risky. This branch does not exist yet, but it will be created when you perform the commit. Describe the addition of the branch in the message box and press the Commit button.
Mercurial now creates the risky branch and automatically performs what is known as an 'update' command to switch the working directory to the risky branch.
Working in your new branch
Now that you're working in the new branch, it's time to create the feature! Here you can see that the feature has been implemented in our main.php source file. You'll also notice that TortoiseHg has put a red exclamation mark overlay on the file in Windows Explorer to show that this file has changed.
Now it's time to commit our feature change to the risky branch. Bring up the Commit view as before. Enter a message about the feature and click the Commit button. It's a good idea to check the Branch each time to make sure you're submitting to the branch you think you are.
The experimental feature has been committed to the risky branch. It does not exist in the default branch. The two branches are considered 'heads' of the revision tree. They're both current as far as Mercurial is concerned. Whichever branch has been committed to most recently is what is known as the tip of the tree. There can be many heads, but only one tip.
Switching branches ('updating')
So we've been happily typing away at our source in the 'risky' branch where our experimental feature lives. Now imagine that the unthinkable happens: you have discovered a fatal bug in the project. Rather than having to fix the bug in the risky branch and push out an untested feature with the bug fix, you can simply switch to the current default branch, make the fix there, and then switch back to the 'risky' branch to continue working on the new feature.
Warning: you will need to commit your changes in 'risky' before switching. If you do not do this, they will be lost (without any big warning messages) when you switch the Working Directory to the default branch. I have tested this with TortoiseHg 2.3 and Mercurial 2.1. But don't worry, after you commit, your source is safe!
One way to perform an update (to switch branches) is to select the Working Directory and then press the Update button in the upper left corner of the Revision Details view. You can also right-click on the last revision containing the branch you wish to switch to and select Update from the context menu.
Then select the name of the branch from the handy drop-down. Tortoise Hg updates the working directory to the head of that branch, thus "switching" you from one branch to the other.
The Working Directory now shows 'default' in the branch column. And all of the files in the project have been "magically" reverted to the last commit in the default branch. It's as if you're working in a completely separate project, but without the hassle or waste of having multiple copies.
The best part is that you can merge branches. Read on!
Merging your branches
You've completed your experimental feature and everyone loves it. Time to merge the feature into the default branch and make it official!
First, switch to the default branch with the update command (see Switching branches ('updating')).
Then right-click on the latest 'risky' branch revision and select Merge with local.
Mercurial will check to see if your merge has any conflicts. Conflicts are simply areas of code which have been edited in both branches. To resolve these conflicts, you can use KDiff3 tool which comes with the TortoiseHg package. It allows you to step through the conflicted areas an select which pieces of code you wish to use.
Once you've resolved any conflicts or there are no conflicts, Mercurial will finish the merge. It will also commit the merge and prompt you for a commit message. You now have a branch which contains the changes from both branches. Very cool.
In summary, the concept of using named branches is really quite simple:
- Commit any changes to the current branch
- Create a new branch and commit
- Make changes to either branch, using update to switch as needed
- Merge all changes when ready, resolving conflicts as needed
TortoiseHg and Bitbucket
Bitbucket already has excellent documentation for Mercurial users. However, there are some aspects of TortoiseHg's interface which are not entirely intuitive. For this reason, the following sections exists largely for the pictures. For more detailed explanations, refer to The Bitbucket Documentation.
Creating a new Bitbucket repository
After creating your Bitbucket account, you can immediately start creating repositories, public or private.
Then you are provided with a URL to which you can push or pull your local repositories.
Pushing changes to Bitbucket
To push your local repository (including all branches and history) to the Bitbucket repository, click on the Synchronize button (two green arrows pointing towards each other). Then enter the Bitbucket URL for the repository. Then click on the Push outgoing changes to remote repository button.
Now you can check out your repository online. Bitbucket automatically shows any README files you may have at the root of the project.
The same steps you took above to make the initial push to Bitbucket can be used to make any subsequent pushes with updates. It's up to you to decide how often you wish to sync your local repository with Bitbucket's. Probably the more developers, the more frequent the syncs should be.
Cloning, pulling revisions from Bitbucket, updating, and merging
Another developer can quickly join a project by cloning the current repository on Bitbucket. To do this, create a directory for the project. Then right-click inside that project directory in Windows Explorer. Then select TortoiseHg->Clone.
Then enter the Bitbucket repository's URL into the Source field and hit the Clone button.
The new developer now has a local repository with all project history and all current files.
The new developer can now commit changes and push them to Bitbucket (if they've been given write permission in the Bitbucket admin settings for the repository.)
Pulling changes made by others is just like pushing. Once the URL has been entered, simply click the Pull incoming changes from the selected URL button and let TortoiseHg/Mercurial do their thing.
After a pull, you're likely to see a "Not a head revision!" message on your Working Directory.
This is Mercurial's way of saying that the revision(s) you've just downloaded from the Bitbucket repository are more recent than any you have committed to the current branch in your local repository. There are two ways to fix this.
If you have not made any commits since the last time you were synchronized with Bitbucket, you can simply run an update to switch to this newer version. See Switching branches ('updating'). Yes, this does mean that the act of pulling new revisions created a new unnamed branch in your repository for that purpose!
If you have made commits since your last pull, you'll need to merge your local commits with this new branch. See Merging your branches.
That's it. Just remember these basic steps:
- Create local repository
- Create Bitbucket repository
- Other developers can clone the Bitbucket repository
- A push sends local commits (revisions) to Bitbucket
- A pull gets new revisions from Bitbucket and puts them in a new, unnamed branch
- After pulling, you'll need to merge or update (switch) branches before you're fully synchronized