Many months ago I read about multiple deployment repositories using Git in this post:
Since then I've taken it a step further with Mercurial. In this post I'm going talk generally about separate repositories for each environment in your Project Universe (Dev, Staging, Live etc), how they can help you automate deployment, and get yourself of some deployment trouble.
When we start a project we normally have a single repository. In Subversion you may develop in the trunk repository. Many people deploy from the trunk. However it is often considered better practice to have a deployment branch. Having a deployment branch means that you merge into this branch when you're ready to deploy. Deployments happen only from this branch. This saves you having to change configurations to deploy from different branches. When the code has been made Live, the trunk must be merged into so that you have a reference to the current state of the Live environment. Note that in Mercurial, we can "clone" - branching is slightly different.
This workflow can sometimes be a problem and is prone to human error. For example, what if a developer forgets to merge to the trunk? Now you've lost your reference to what is Live. What does the next developer do when they need to fix a bug? Also, how do you deal with a situation where a feature is waiting to be pushed live, but a bug fix must go up first?
Taking deployment repositories a step further...
Having separate deployment repositories means that your Live repository is always going to reference what is Live. Moreover, you know exactly what is on Dev, and Staging etc.
Some people think that multiple repositories is overkill and a lot of extra work. But having separate deployment repositories also means that you can now automate deployment to your different environments. All you need to do is set up a build trigger on your Continuous Integration server. For example, when a change in the Dev repository is detected, build and deploy. Automating your deployment is extremely powerful.
If it still sounds a bit overwhelming, consider these user stories:
"As a developer I want to drop my new code in a deployment box, so that when it gets dropped in there, an automatic build is triggered, and deployment to the development server occurs".
"As a developer I want to drop my new code in a deployment box, so that when it gets dropped in there, an automatic build is triggered, and deployment to the staging server occurs".
So think of these deployment repositories NOT as repositories, but as boxes where your code goes to get deployed. The fact that these deployment boxes are actually full featured code repositories gives you much more power and more options. For example, Developer 1 has features sitting on Dev and Staging waiting to be deployed. Developer 2 has fixed some bugs but doesn't know about Developer 1's changes. When Developer 2 tries to push to the deployment box (repository) for deployment to the development server it will fail. This is a positive thing because Developer 2 now knows that there was actually other work being done, and that they should communicate with Developer 1.
To deploy to the development server, Developer 2 will simply strip Developer 1's changes on the deployment repository before pushing the bug fix. Developer 2 will also encounter this on Staging, but not on Live because the features were not pushed Live yet. For Developer 1, they will encounter a similar issue when instructed to push the changes Live. Developer 1 now knows that they must merge the bug fix into the feature set before trying to deploy again. And of course going through a proper testing a deploy process to ensure stability of the merged bug fixes. Mercurial and Git make merging automatic (or at least very easy compared to SVN) as much more information is kept for each change set.
We've talked about deployment repositories, but where is it that you are doing your work? Ie. where is your working repository? It doesn't matter how you structure your working/feature/maintenance/main repositories. They can be anywhere you want. All you need to do is put your code into the deployment box for where you want to deploy to.
Hopefully you've been convinced that multiple deployment boxes (repositories) is much more powerful and actually makes your life easier when you couple it with automated build and deployment from a Continuous Integration server.
My controversial statement of the day: I'm sure you can do something similar using TFS and Subverion. But personally I think that if you're not using Mercurial or Git then you're living in the dark ages of version control. And if your company doesnt want to move to a distributed version control system you might consider changing companies, because they're probably holding you back as a developer.