As far as I can tell, what you're asking about is how to handle different branches of development in Mercurial. In your example, you want to easily be able to release fixes to the release version without having to deal with all the stuff that has happened in the development branch since the last release.
There are many ways to handle branches in Mercurial. You can use separate repositories, named branches and the Bookmarks extension among others. How you choose to handle branches in Mercurial is related to the type of workflow you have but there are many possible combinations.
With that in mind, I will give some general suggestions for workflow between branches, regardless of how they're represented in Mercurial (as separate repositories, named branches etc). If you want to learn more about what branching model to choose I suggest you read Steve Losh's guide to branching in Mercurial and my blog post on choosing a branching model in Mercurial.
First of all, even with no branches at all, you can still always go back to an earlier revision of the code, e.g. the 2.0 release, and fix the bug there. This will make it easy to tag and release a new version (say 2.0.1) with the only change being the bug fix.
You do this by simply updating, fixing and committing:
$ hg update 2.0
hack hack hack
$ hg commit -m "Fix nasty bug"
$ hg tag 2.0.1
The above assumes you have tagged the 2.0 revision so it's easy to get at it, otherwise you will have to supply a hash or revision id instead.
This will give you two heads, which you can merge with hg merge
, bringing the fix back into the development version.
If you have a separate repository for the 2.0 release, you make the fix there and then pull it into the development repository where you then merge. The basic principle is the one Ry4an outlined, you make the change where there isn't already a bunch of other changes made that you don't want.
Here's an example:
Where I work we many repositories representing different branches. Most development happens in the "dev" branch. When a release nears, we clone that repository into a new one called say "release-2.4". In this branch/repo we test and fix bugs for the upcoming release. More experimental development that won't be ready until the next release can happen in "dev" in parallel.
When the release is tested and ready to go out, we pull everything from "release-2.4" into "prod", which only contains released versions of code. We tag it with a version number and release it to the world. We can then delete the "release-2.4" branch, and pull everything from "prod" into "dev". This might require a merge, but then we have all the changes made during the release process back in "dev" and can continue working on the next release.
If we want to fix a bug outside the bigger planned releases, we can do it a couple of ways. If the fix is small (a couple of commits) or doesn't involve many developers, we can just commit directly to "prod", tag the release and the ship it. After that we pull from "prod" into "dev" to make sure the fix is there in the next release as well.
If the bug fix release is larger and will take more time, we can instead make a new branch off "prod", do all our work on the release there, and then pull the changes into "prod". When it's released into "prod", we can then "pull" from "prod" into "dev" to get the changes there. The special release branch can then be deleted.