I'm trying to find the best version control strategy for my workflow with Drupal. I have multiple sites per install and I'm pretty sure I'll have a separate repository for each website. As far as I know, the VCSs worth considering are:
- SVN
- Bazaar (bzr)
- Git
- Mercurial (hg)
I know how these compare to each other in general, but want to learn their merits/demerits for Drupal. If you're using (or have used) any of these for Drupal:
- What is your setup?
- What about the VCS you chose works well for managing Drupal projects?
- What doesn't?
Another subversion setup here.
Basic setup is:
- We track Drupal core and all contributed modules/themes we use each within their own folder in one part of our repository
- Each of those has one subfolder 'drop', where new versions are copied into, once we start to use them.
- Then we commit this as 'dropped version 6.x-y' - this leads to a local history of the release versions of Drupal core or the module in question (redundant to the 'official' cvs history at drupal.org, but more convenient to search/diff in case of problems)
- Then we create a branch for the drop, named after the version (e.g. drupal-6.15, views-6.x-2.8) - this will normally be just used as is (see 'externals' below), but also serves as the baseline for custom changes to the module, if we need them. We try to avoid changes to core or contributed modules, but sometimes we need to fix a bug and can not wait untill the fix eventually ends up in an official release. So we make our changes and commit them on that branch. Once a new version comes in, we can diff it against our branch and eventually reapply the fix to the new versions branch, if it does not incorporate the fix already. This way, we have a complete and reusable overview of all core and module versions we use in different projects, including any customizations we eventually needed.
- For each of our Projects (sites), we create the usual SVN trunk/branches/tags hierarchy in a different part of the repository
- We then use Subversions 'externals' definitions to pull in the core version, as well as all the additional modules we need from the branches described above. The important part here is that we can pull any version we need, so some sites might use a specially patched version of module x, while others might pull an unpatched previous version, and yet another uses the latest and greatest official release - we don't have to keep track of this mess, as SVN can tell us exactly what gets used when and where, at all times!
- Then we add our project/site specific stuff - settings file(s), .htaccess files, project specific modules/themes, etc.
- New development happens on trunk
- Once we reach a release point, we create a release branch and tag that
- We export that tag to the test/staging/live servers as needed
- Meanwhile, new development can continue on trunk
- Should we need to apply a fix to the current release version, this happens on the release branch
- Again, the fix gets commited, tagged and finally exported and deployed
- Should the fix be something needed in general, it gets merged back onto the trunk, so that it will be available in future versions in general
- Lather, rinse, repeat ...
Pros:
- Mainly, a quite complete overview of all things that ever happened to any code within any of our projects :)
- Especially, the ability to track and reuse different versions of core or contributed modules within different projects, even with arbitrary custom changes, without creating an unmanageable mess (When, why and where did we use this custom one line fix within pathauto, and when, why and where did we stop using it - SVN logs will answer that)
- Reproducible deployments - should anything go wrong on a production server, we can export the exact set of code used there, with all one time fixes, adjustments and 'specialties' on the spot (obviously only useful in conjunction with proper database backups ;)
Cons:
- As easily to be seen from the descriptions above, this setup creates a bit of an administrative overhead when importing new core/module versions (and most of the time it even seems needless, as applying special fixes is a rare thing to do)
- Using externals definitions extensively like that makes update operations to the local checkout a bit more lengthy
- When a changeset implies a combination of changes to both, the project itself and a custom module imported via externals, it will not be an atomic commit, as they have to be checked in separately!
Conclusion:
As long as you have to manage only a handful of projects/sites, this might not be effective, and you might be better of committing and maintaining the whole setup (core, contrib and custom stuff) combined within one branch.
But I can assure that once you have to manage 10++ projects in parallel (some on 5.x, some on 6.x, all at different update and/or customization levels, often reusing the same customizations), being able to tell what code gets used where exactly is a huge relieve!
PS: Rereading my sermon, it is somewhat obvious that it does not really address your question regarding the merits of different VCS as compared to each other - sorry for that, but maybe it helps anyway ;)