How I use Git for my Drupal sites

I have a server with several Drupal websites on it. I want a separate codebase for each so that I can tweak, play on one without affecting the others. I like using Git. This page documents (for my reference as much as for your delight!) my workflow.

Advantages:

  1. control: full access to all of Git's history. Downgrades available!
  2. robustness: separated Drupal codebase between sites.
  3. space: minimises disk usage through local clones.
  4. access: models a centralised repo structure enabling code to be exchanged between servers without fixed IPs, e.g. my laptop.

My set-up is as follows

  1. A bare repository on my server which includes drupal core and a branch for each of my sites.
  2. Each live site's branch comes off at the current stable tag, e.g. 7.8.
  3. My separate development server clones the site branch from the bare repository.

Setting up the bare mirror repository

git clone --bare --mirror http://git.drupal.org/project/drupal.git \
                          /path/to/bare/repo

The mirror option means that the remote's branches are brought in as local branches; they are not stored in refs/remotes/origin/... but in refs/heads/...

This is exactly what we want. If you didn't start with mirror, you can create the config later with git config. It looks like this:

remote.origin.fetch=+refs/*:refs/*
remote.origin.mirror=true
remote.origin.url=http://git.drupal.org/project/drupal.git

The + in the fetch refspec means that source refs will overwrite destination ones even if it's not a fast forward update. There is a danger here that if I create a branch with a name used (now or in the future) by the origin, then my branch would be overwritten and lost. But as long as I stick to domain names for branch names, I figure I'm fairly safe.

Setting up a new site (e.g. at Drupal 7.8)

The clone is fast and space efficient thanks to hard linking (assuming it's on the same partition as the bare repo).

git clone /path/to/bare/repo newsite

I then create a new branch with the name of the site, from the stable tag:

cd newsite; git checkout -b newsite 7.8

And finally, I push this branch onto the origin

git push origin newsite

Setting up a developement server for the site

This is straight forward:

git clone me@remoteserver:/path/to/bare/repo newsite
git checkout -b newsite newsite
It is possible to specify a branch at the point of doing the clone. This means you local master branch points to a differently named branch on the remote. I find this leaves room for ambiguity and error, which is why I prefer to create named branches.

Normal development

Work on the development server is committed locally, then pushed up to the bare repo'. This is easily pulled down into the live site.

Dev:sitebranch → Bare:sitebranch → Live:sitebranch

Likewise this process occurs in reverse if I do a quick fix on the live site. And I always pull before attepting to push, of course, because you can't resolve conflicts in a bare repo.

As my development server does not have a fixed IP, I would not be able to pull commits directly from dev into my live working trees. So the bare repository, hosted online, enables this process.

Upgrading Drupal, e.g. to 7.9

First, the bare repository needs to fetch all the great work that's gone into Drupal since it last checked.

cd /path/to/bare/repo
git fetch --all

Now our bare repository has all the commits needed for 7.9 (and some) I can pull all the commits since my original checkout (which might be 7.8, say) with

cd /path/to/dev/site
git status                 # check working tree is clean!
git merge 7.9              # ...
git push origin sitebranch 

Occasionally I prefer to rebase, to maintain all my changes 'on top' of the current drupal core.

cd /path/to/dev/site
git checkout -b sitebranch-backup  # always make a backup!
git checkout sitebranch            # return to our site branch
git rebase 7.8                     # ...
git push --force origin sitebranch # non-linear update needs forcing

And when I'm sure there's no error, I delete the backup with git branch -D sitebranch-backup

Modules, themes, core all in one repo?

No. I use the method above for the main drupal core files. Not that I'd ever patch core ;-)

I usually keep modules etc. in separate repos, but again using a similar central bare repo setup.

Key git tools

I find myself using these a lot:

  • git show-branch --color [-a | <ref> [<ref>...]]
  • git fetch --all
  • git help <command> !

 

Tags: 
Pull Out: 

Bare and mirrored repositories provide a lot of flexiblity.

Add new comment