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.
- control: full access to all of Git's history. Downgrades available!
- robustness: separated Drupal codebase between sites.
- space: minimises disk usage through local clones.
- 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
- A bare repository on my server which includes drupal core and a branch for each of my sites.
- Each live site's branch comes off at the current stable tag, e.g. 7.8.
- 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
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
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.
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> !
Bare and mirrored repositories provide a lot of flexiblity.