Using Git with Acquia Hosting

As Drupal grows in popularity as a robust enterprise-grade CMS, there is a growing need for high quality hosting. One of the more interesting alternatives is Acquia Hosting - a specialized Drupal hosting solution from Acquia. Acquia is the firm co-counded by Dries Buytaert, who also started the Drupal project in 2001. Acquia's Drupal hosting platform is based on the Amazon cloud infrastructure and is highly optimized for the requirements of Drupal. We have used their hosting for one of our latest projects to great success. note: Dynamite Heads is an Acquia Partner.

The hosting is definitely top quality, however we stumbled while trying to solve one issue: Acquia Hosting uses Subversion for code deployment, but our system of choice is git. It's worth noting both that drupal.org is moving away from CVS to git and I hope Acquia will also consider deployment via git in their hosting products. For now though, we had to look for a way to join these two together version control systems for this project so that we could:

  • use Git for development
  • and keep Subversion for Acquia Hosting

Start in Git, continue in Subversion

If you are familiar with Git you would say: use git-svn. Unfortunately, it’s not that easy - git-svn is used when you have a Subversion repository as the canonical repository and you want to use Git for independent development. We did the opposite - started in Git and now need to push to Subversion.

There are few howto’s out there, but none of them worked properly. We then found a better solution: git-svn commit-diff. This command eliminates the need to integrate with SVN directly. Instead, it takes two git trees and commits a diff to SVN - exactly what we needed!

The workflow is very easy: Using your local git repository (a clone is fine since git is a distributed VCS), write down the commit if you want to have as the initial SVN commit and manually copy all of these files to Subversion, then commit there. Once you update anything in Git, just take the last commit number and use:

git svn commit-diff -r <last_svn_revision> <old_commit_tree> <new_commit_tree> svn://svn-url

Git makes a diff between the last SVN commit and the latest version and commits it to SVN. And that’s it :-)

To show the complete workflow, the exact steps are listed below. (This requires a Linux/Unix shell)

Step 1: Make sure your Git repository is clean

Your entire deployment will fail if you ever (accidentally) checked out files from Subversion. In the first step, we need to make sure that you don’t have any .svn files in your Git repository. You can do that for example using find:

git clone <git_url> svn_preparation # Make a clean git clone.
# Optionally switch to a branch you want to use.
cd svn_preparation  # Switch to Git clone.
find . -type d -name “.svn” -exec git rm -r {} \; # Delete all directories called “.svn”
git status # Review all changes
git commit # Commit changes
git push # Push changes

Now look in git log and mark the number of this latest commit. Example:

# git log
commit 53501df5b2fbf0d30b014f118db41443513f7d39 # save this string somewhere
Author: Jakub Suchy <jakub@dynamiteheads.com>
Date:   Wed Aug 18 12:57:51 2010 +0200

Let’s call the string 53501df5b2fbf0d30b014f118db41443513f7d39 <commit id>

Step 2: Commit initial version of the files to Subversion

First, make a checkout from subversion and commit the current version of files from Git there:

svn checkout svn://...url/
cd <new_checkout>
cp -r /path/to/previous/git/clone .
svn add *
svn commit -m “Initial commit based on <commit id>”

Do the same as in Git, type svn log and write down the subversion revision number.

------------------------------------------------------------------------
r29 | git | 2010-08-18 14:55:11 +0100 (Wed, 18 Aug 2010) | 4 lines  # Note number 29
Merge commit 'origin/store_locator'

Step 3: Commit changes from Git to SVN

You have code in SVN based on a certain commit from Git. Some time has passed and you have made changes in Git. Now you want to push them to SVN. How? Use git-svn with it’s commit-diff functionality.

As a first step, update your Git clone (with git pull) and look in git log. Mark the new commit identification string (let’s call it <new commit id>) on which you want to base the changes and run:

git svn commit-diff -r 29 <commit id> <new commit id> svn://svn-url

As an example:

git svn commit-diff -r 29 53501df5b2fbf0d30b014f118db41443513f7d39 a1d7ad10111f747ce79394f2aa936f59f31dc6cd svn://bal-1.prod.hosting.acquia.com/repository/

One note: Why -r 29? Remember we noted revision number in our last SVN commit?

The Git scripts will now automatically commit all changes to Subversion. Make a note of the new Subversion revision. Your <new commit id> now becomes <commit id> and you can repeat this step as you wish.

Step 4: Create a documentation

Do not forget to note of all the commit identification strings in your documentation. You will need them later when you commit changes again as you probably won't be able to retrieve them from history. Best place is to put it into your project documentation every time you commit a changeset.

Step 5: Enjoy

After performing steps above, you will be able to continue your development in Git repository and push changes to Subversion whenever you want. Enjoy and as usual, don't forget to contact us if you need help with your Drupal development or Git integration.

P.S.: Thanks to Andrew Burcin for necessary help with this howto.

Jakub Suchý

Jakub is owner and founder of Dynamite Heads. Jakub is a member of Drupal Security Team and supports Czech Drupal community at Drupal.cz