I have a setup I'm pretty proud of, and it works extremely well for my team.
General Structure
I keep the entire installation under git. All changes, be it a system update, adding/updating a plugin, adding/updating a theme, go through the same workflow. Changes can be rolled back at a moment's notice. I have a deployment server (an old P4 desktop) running gitosis but you could just as easily use github or gitolite. In git, I have two "special" branches, master
and develop
(explained more below). My production and staging servers are cloud-based.
Development Environments
Every developer runs their own development server on their own machine. In terms of databases, needing live data has hardly ever been an issue. We mainly use the theme unit test data. Otherwise export and import covers most things. If the DB piece was crucial, you could setup replication or setup something for on-demand syncing. When I initially setup this structure, I thought this would be crucial so I started writing a set of tools to do this, but to my surprise they really weren't necessary. (note: since they weren't necessary, I didn't ever polish them up, so there are bugs e.g. it will replace the domain in serialized data).
Staging Environment
When commits are pushed from the develop
branch to gitosis, they get automatically deployed to our staging server. The staging database is a slave to the production database.
Production Environment
When commits are pushed to gitosis on the master
branch, it's automatically deployed to the production server.
The wp-config.php issue
You want wp-config.php
to be unique from server to server, but you also want to keep it under version control. My solution was to use .gitignore
to ignore wp-config.php
, and store the staging and production versions as differently-named files. Then on each server, I symlink e.g. wp-config.php -> wp-config-production.php
. Each user then keeps their own DB with their own credentials, with their own (untracked) wp-config.php settings.
Other Notes
I use Rackspace Cloud, which is phenomenal and inexpensive. With it I can keep my staging and production servers identical. I'm also writing plugins right now that use their API to allow me to control my services right from within WordPress, it's wonderful.
Cache directories, file upload directories, etc., are all added to .gitignore. If you wanted, you could setup a cron task to routinely check in uploads and push them to gitosis, but that never seemed necessary to me.
The master/develop structure is set to partially mimic Vincent Driessen's branching model. I also use his git extension git-flow and I'd highly suggest that as well.
I've had 10 or so developers working off this structure for over a year now and it's been a dream to work with. Reliable, secure, fast, functional, and agile, you can't ask for much more!