I will be more specific with a question if I need to be, or make this into a community wiki if you all think that’s where it fits, but my question is:
My dev team has recently started using Mercurial (moved from subversion) and we love it so far. I’m wondering if there is a ‘best practices’ resource out there about repository architecture. What I’m interested in is, what is the best way to leave a stable copy of the repo (for shipping/emergency bug fixes) while working on features and new versions. I have read a lot about named branches vs. cloned repositories and I’m hoping some of you hg guys can shed some light on what works for your team.
What is easier to merge after a feature has been tested and is ready for the next release? Are there any serious drawbacks to the 2 methods I have mentioned? Are there other repo management strategies out there?
We are nearing the deployment of our 2.0.0 release and I’m looking to start fresh once it is out with a new way of working with hg.
Let me rephrase to hit on some basics that I’m still struggling with – Let’s say I finish 2.0.0 tomorrow… I want to start work on 2.1.0, what do I do? Clone my repo, name it “working/projects/widgets2.1” and keep rolling along, having my “workin/projects/widgets2.0” sitting there ready to be used in bug fixing situations?
Further, if the customer calls and says there is a bug and the widget machine is shaking and smoke is starting to billow, do I pop open widgets2.0, fix the bug, deploy to server, then commit/push? Do I then go back over to widgets2.1 and pull/merge that bug fix?
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:
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 have 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.