WordPress, Version Control, and Staging Sites
How to tackle the unique challenges of using Git version control with a WordPress website.
WordPress doesn’t play well with Git because the media library and third-party themes and plugins get updated frequently and often affect the database. This makes the repo hard to manage and makes rolling back changes difficult since the database state needs to match the working directory state. There are a few ways to address this problem.
What to put in the repo
To avoid production and dev DBs from getting out of sync we can:
- Make simple CMS additions and edits directly to live site
- Take automatic daily staging/production backups (90 days of backups) – if anything ever gets out of sync, *any admin* can restore a snapshot from the WP dashboard
- Keep *only* custom themes and plugins under version control
Keeping Staging & Production in-sync
This method will mean production will get ahead of the upstream master repo under the current system every time we update a plugin. That’s why I recommend removing WP core, uploads, and all plugins and themes we didn’t create out of the repo. Just our child theme and custom plugin would be in the repo in this case. This will reduce complexity, make the repo smaller, reduce the number of commits, make it easier to keep the repo up to date.
Method A: No database changes
Filesystem changes (no DB changes) need to be tested in dev first (e.g. we want to fix a theme bug)
- Migrate production to dev
- Make changes to dev and push to repo
- Pull from repo to production
Method B: Database changes
Filesystem and DB changes need to be tested in dev first (e.g. we are doing a major site redesign)
- Migrate production to dev and put production in maintenance mode ideally*
- Make changes in dev and push to repo
- Migrate backup to production
- Sync repo in production (Git fetch + reset –hard origin/master)
*if we can’t put the site into maintenance mode, we need to make sure no manual changes are made to the WP DB and any important automatic changes are merged (frontend user registrations, for example)