The last time I talked about version control, I discussed why you should use version control for your solo developer project, some of version control systems you have as options, and some reasons I chose Mercurial. Now, I want to talk about using Mercurial to solve a typical development problem: concurrent development.
The Problem and a Solution
Suppose that you have come to a 1.0 release (just as I have, about two weeks ago). At this point, it is not unreasonable for your development to branch. In the first branch, you want to start work on 1.0.1. Here, you’ll have small bugfixes to your 1.0 release. (For example, I’ve added a “reset to defaults” option in preferences, and I found a typo in the help files.) In the second branch, you want to start work on 1.1. Here, you’ll revise or add a feature to your 1.0 release. (For example, I am adding some inference rules in 1.1, and simplifying preferences.)
Why not just copy your original 1.0 release code into two additional directories, label those directories 1.0.1 and 1.1 respectively, and be done with it? Well, here’s the thing: the small bugfixes I’m planning to roll out as part of 1.0.1 will also apply to 1.1. And while 1.0.1 will be released much sooner than 1.1, I want to begin work on 1.1 immediately. So, how do I make sure the small bugfixes in 1.0.1 are transferred to the code I’m working on in 1.1? Well, I could just do a lot of copying and pasting. That’s what developers did before version control, after all. But this wastes time, and it is possible that I will make some copying mistakes. The elegant solution is to use branchy development under version control.
Growing Branches
Imagine that your project directory is called “1.0” that is a Mercurial repository, and you have a file, Myfile.txt that is part of that repository:
1
2
3
4
5
You release your program, and Myfile.txt goes out the door with it. Now, you want to start work on 1.0.1 and 1.1. First, clone your 1.0 repository twice, as follows:
hg clone 1.0 1.0.1
hg clone 1.0 1.1
Now you have two copies of the 1.0 directory, conveniently named 1.0.1 and 1.1. Now, cd into 1.0.1, and change Myfile.txt to look like this:
1 – Minor change
2
3
4
5
And cd into 1.1, and change Myfile.txt to look like this:
1
2
{ Big change here }
3
4
5
So, let’s imagine that you’re happy with the change you made to 1.0.1, and everything is working without a hitch. You commit the change to 1.0.1 the repository. You’re still hacking away at 1.1, but you’d like to incorporate the change you made in 1.0.1 (a change that is unrelated to the changes you are making in 1.1). How do you do this? Well, first, cd into 1.1. Now issue the following commands:
hg pull ../1.0.1
hg merge
hg commit -m ‘Merged 1.1 with 1.0.1’
This will integrate the changes you made in 1.0.1 into your 1.1 repository. When you issue pull, you bring in the changes from 1.0.1, but do not update the files in your working directory. It is merge that updates the files in your working directory. Finally, you commit the results of the merge to the 1.1 repository. You will get the following result:
1 – Minor change
2
{ Big change here }
3
4
5
It goes without saying that you should have a backup of your repository and files before you start doing this sort of thing for the first time, just in case things do not go as planned. For more information on branchy development, I suggest you have a look at The Basics and Merging Work, both chapters of Mercurial: The Definitive Guide.