I use Subversion and a concept called 'vendor branches.' Sadly, their documentation is confusing and not as easy as what I'm going to describe. Let us use an example to demonstrate.
At work we rely on JiveSoftware's JiveForums software to host our forums. Each time they come out with an upgrade, what is the easiest way to deploy that upgrade across our development, preview and production environments? The answer is to check a copy of their code into subversion. This is an example script of how I do an upgrade from version 5.5.0 to 5.5.7. This assums that 5.5.0 has already been added using steps similar to below.
- wget http://domain/jive_software_5.5.7.zip
- unzip jive_software_5.5.7.zip
- svn co -N http://svn/vendor/jivesoftware jivesoftware
- mv jive_software_5.5.7 jivesoftware
- cd jivesoftware
- svn add jive_software_5.5.7
- svn ci -m 'adding a clean download of 5.5.7'
- svn co http://svn/dev/jive jive-dev
- cd jive-dev
- svn merge --ignore-ancestry http://svn/vendor/jivesoftware/jive_software_5.5.0/ http://svn/vendor/jivesoftware/jive_software_5.5.7/ .
- svn ci -m 'upgraded development environment to 5.5.7'
For deployment of code to our preview and production environments, we have just checked out the preview/prod trees from svn onto the individual servers. Upgrading preview/prod is the same steps as above. Upgrading the machines themselves means that we just need to do an 'svn up' or 'svn switch' if we decide to deploy based on tags. At some point we might use .deb's to do these deployments, but for now, subversion is a great solution. It is especially handy to be able to quickly see a nice diff if a file changes because someone logged in over the weekend and needed to quickly modify a file by hand.
Running JBoss through this system works exceptionally well because not only does each revision move files around significantly, but it is increasingly difficult to even remember all the modifications we make to various configuration files for our preview and production servers. This process gives us the nice ability to use diff's to easily find those changes.
As for gotchas, one major one that I've discovered during upgrades of JBoss is that they will frequently take a packaged set of files (ie: a .sar/.jar file) and explode them into a directory. Unfortunately, subversion doesn't deal with this problem very well. It gives an error about 'type of resource object has changed.' When this happens, what you need to do is delete the file from your local repository first (including committing this change) and then doing the merge. The other gotcha is to make sure that all your text files go in with 'svn:eol-style = native' line feeds set from your .subversion/config file. If you get files with mixed linefeeds, the merge process doesn't always work so well and generates a lot of conflicts.
Well, that's it. I hope that little howto has been helpful.