Development sandbox with Git and Drush

Antonio De Marco
13 Apr 2010
0 Comments
Antonio De Marco
13 Apr 2010
0 Comments
Antonio De Marco, 13 Apr 2010 - 0 Comments

Development sandbox with Git and Drush

Keep things neat.

I bet every Drupal developer keeps a Drupal installation as local sandbox where they try out code snippets, maintain modules or generate patches to be contributed back to the community. If not well maintained this installation will, day after day, grow into a chaotic mess of content and settings. Having separate Drupal installations for each project we work on would be a good solution here.

"Divide et impera" with Git

Git is one of the rising stars in the version control system world and the main candidate in replacing the obsolete Drupal CVS infrastructure. After installing Git, setting up a repository is a piece of cake, in your project root type:

$ git init

and there you go, you are now ready to commit, branch, merge or revert your sandbox code. Having your code under version control is generally a good practice: you can be sure that nothing will get really lost and, more important, you can branch your code according to what you are working on, to help keeping things in order. To create a branch using Git type:

$ git branch my_module

You can list all your branches by typing git branch, you'll be working on master branch by default:

$ git branch my_module
  my_module
* master

To actually move the development to that branch type:

$ git checkout my_module

After applying your changes you can commit to the branch and move back to master to do something else. You can learn more about a normal Git workflow here, for more information about branching have a look at Basic Branching and Merging.

You can branch your sandbox per module, appending version information if you wish, and everything will be safely separated. On my local sandbox the situation looks like this:

$ git branch
  context-6.x-3.0-beta4
  faceted_search-6.x-1.x-dev
  feeds-6.x-1.x-dev
* master
  node_widget-6.x-1.x-dev
  openlayers_geocoder-6.x-1.x-dev
  openlayers_geocoder-6.x-2.x-dev
  timeline-6.x-2.x-dev
  unlimited_css-6.x-1.x-dev

The sandbox is divided per module and version: this division makes it easy to change the development focus quickly just by checking out different branches. Let's say a new bug needs to be fixed in the OpenLayers Geocoder module, 2.x branch, we type:

$ git checkout openlayers_geocoder-6.x-2.x-dev

A CVS checkout of the module is available under sites/all/modules/devel/openlayers_geocoder/ (CVS metadata are also committed to Git). After fixing the bug we run:

$ git commit -a -m "Fixing a bug."

and we are now ready to focus on something else. What shown so far is not going to work correctly for the very simple reason: code is not (yet) the king in Drupal, the database is. All settings and content you use to develop and test your code is, obviously, stored into the database, what we need to do is to dump and commit the database:

$ git checkout master
$ drush sql-dump --result-file="dump.sql"
$ git add dump.sql
$ git commit -a -m "Adding dump."

This must be done in the master branch before branching, so we will always carry our dump along. After changing branch (e.g.: git checkout my_module) we must remember to restore the dump in order to have our Drupal sandbox work correctly. It's clear that the database restoring must happen after every checkout.

Automation with Drush and Git hooks

Git, as other version control systems, exposes a series of hooks. Hooks are bash scripts that are ran in conjunction with a specific Git event. The main Git hooks here are located under .git/hooks directory:

  applypatch-msg.sample
  commit-msg.sample
  post-checkout.sample
  post-commit.sample
  post-receive.sample
  post-update.sample
  pre-applypatch.sample
  pre-commit.sample
  pre-rebase.sample
  prepare-commit-msg.sample
  update.sample

If we are interested in post-checkout.sample: to activate a hook we just need to remove the .sample extension. In order to automate our dump restore we paste into post-checkout the following code:

  #!/bin/bash

  # $3 is equal to 1 in case of a branch switch or after git clone, 0 otherwise
  if [ $3 ]; then
    echo "Restoring database."
    drush sql-cli < sites/all/database/development.sql
    echo "Clearing cache."
    drush cc all
    echo "Done."
  fi 

This bash script restores the database and clears the cache. We are now able to switch from one branch to another carrying along all our content, settings, etc.:

$ git checkout node_widget-6.x-1.x-dev
Checking out files: 100% (933/933), done.
Switched to branch 'node_widget-6.x-1.x-dev'
Restoring database.
Clearing cache.
'all' cache was cleared
Done.

$ git checkout openlayers_geocoder-6.x-2.x-dev
Switched to branch 'openlayers_geocoder-6.x-2.x-dev'
Restoring database.
Clearing cache.
'all' cache was cleared
Done.

On the other hand, dumping and committing the database before switching branch is not automatic since we want to have control of what changes need to stay: it will happen that you just checkout a branch, make a quick test and you want to forget about it.

Getting to the speed of light: Git bash completion

If you want to attach name code version to your branch or other information you will end up having really long branch names. If you don't want to type them all the time get to the speed of light with Git bash completion.

Get your project started today!

Contact us