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<br> my_module<br>* 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<br> context-6.x-3.0-beta4<br> faceted_search-6.x-1.x-dev<br> feeds-6.x-1.x-dev<br>* master<br> node_widget-6.x-1.x-dev<br> openlayers_geocoder-6.x-1.x-dev<br> openlayers_geocoder-6.x-2.x-dev<br> timeline-6.x-2.x-dev<br> 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<br>$ drush sql-dump --result-file="dump.sql"<br>$ git add dump.sql<br>$ 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<br> commit-msg.sample<br> post-checkout.sample<br> post-commit.sample<br> post-receive.sample<br> post-update.sample<br> pre-applypatch.sample<br> pre-commit.sample<br> pre-rebase.sample<br> prepare-commit-msg.sample<br> 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<br><br> # $3 is equal to 1 in case of a branch switch or after git clone, 0 otherwise<br> if [ $3 ]; then<br> echo "Restoring database."<br> drush sql-cli < sites/all/database/development.sql<br> echo "Clearing cache."<br> drush cc all<br> echo "Done."<br> 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 <br>Checking out files: 100% (933/933), done.<br>Switched to branch 'node_widget-6.x-1.x-dev'<br>Restoring database.<br>Clearing cache.<br>'all' cache was cleared<br>Done.<br><br>$ git checkout openlayers_geocoder-6.x-2.x-dev<br>Switched to branch 'openlayers_geocoder-6.x-2.x-dev'<br>Restoring database.<br>Clearing cache.<br>'all' cache was cleared<br>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.
Tags: Drupal Planet, Drush, GitImage: