Drupal project workflow and version control with git – now 90% less complicated!

Edit: Since this post was created, I’ve since changed my Drupal development workflow (again) and would no longer recommend this approach. Instead, we’re now using a versioned drush-make script and aegir. A new workflow post is coming, eventually.

The last workflow with Drupal and git I posted about was complicated. This is much simpler.

  1. Create a project directory and start a git repository: mkdir my_project && cd "$_" && git init
  2. Into this directory, check out the Drupal base as a submodule: git submodule add http://git.drupal.org/project/drupal.git drupal
  3. Once the submodule has finished loading, go into the submodule and check out the version of Drupal that you want to use. In my case, the most recent 7.x.: cd drupal && git checkout 7.9
  4. Install Drupal as normal. Point your webroot  (or however you’re accessing the site) at the Drupal directory within your project directory.
  5. Move the sites directory out of the drupal directory and into the parent directory. Create a symlink back into the drupal directory: mv sites .. && ln -s ../sites This will let you use git to manage the sites directory, while still letting Drupal think everything is normal. Additionally, it will make it easier to update the Drupal version using git.
  6. Modules and themes are installed by adding them as submodules to the sites directory now. I usually put all downloaded modules/themes in a directory called contrib and all custom modules in a directory called collab, but there is no need for you do to this if you don’t want to.
  7. (Adding a module) Let’s add, for example, the Git Deploy module to our site. git submodule add http://git.drupal.org/project/git_deploy.git sites/all/modules/contrib/git_deploy && pushd "$_" This will clone the submodule and put you in its directory, where you can choose which version to run by performing git tag then git checkout version_foo. Use popd when you’re done to return to the project root.
  8. Using the Drupal interface, install/activate the module normally.
  9. Repeat as needed.

I mentioned the git_deploy module above, since if you’re using this workflow that module is necessary for Drupal to be able to determine when modules need to be updated. Without it, you’d have to check every submodule manually with git.

To update a module, you simply cd into the directory, git fetch to update the module, then git checkout new_version. Don’t forget to update the database using update.php as normal for Drupal.

Updating Drupal core is not much more difficult. Simply remove the symlink, fetch and checkout the new version, re-add the sites symlink, and update the Drupal install as you normally would. I keep the following script in the project root directory to save me the two seconds it normally takes to do this:

#!/bin/bash

rm -rf ./drupal/sites
ln -s ../sites ./drupal/sites

That’s it! It’s pretty simple, and the majority of the usage once everything is set up is just adding submodules over and over as needed. It has the benefit of not storing any drupal code in your local repository (only submodule configuration information and custom code) and has the benefit of being easily extensible to storing your own custom modules in a different repository and adding them the same way. Other developers can easily re-create the installation by cloning your project repository recursively.

As always, suggestions for improvements are welcome.