brandonmartinez

Deploy WordPress Using Git

With this site’s recent migration to Windows Azure, the true power of Git-based deployments has become very apparent. Being able to source control an entire WordPress site, including plugins, themes, configuration, and of course, WordPress itself, makes it very convenient to manage. Adding automatic deployments just sweetens the deal.

If you’re not running on Windows Azure, but still want to take advantage of Git-based deployments, it’s a relatively easy process to setup. I’ve tested this setup on multiple sites and it’s been working very well for me.

Assumptions

A few assumptions are made for this tutorial:

  • You are at least somewhat familiar with using Git from the terminal/command line.
  • Your WordPress site is already stored in a Git repository (including WordPress, themes, plugins, etc).
  • You have SSH access to your web server.
  • You are allowed to run shell scripts on your web server.
  • This tutorial is pretty Mac-oriented, but this could be done easily on Windows or *nix.

Step 1: Setup a Passwordless SSH Login

Technically, this step is optional, but it makes it a ton easier to deploy your code. I’ve written on how to do this before, but I recently found a cool homebrew script that makes the process a lot easier: ssh-copy-id.

To install it, run this from the terminal:

$ brew install ssh-copy-id

You can then push your shared key to your server by running this command:

$ ssh-copy-id {USER NAME}@{DOMAIN NAME}.com

You should be prompted for your account’s password; enter that and it’ll complete the process.

Step 2: Prepare the Server

Remote into your web server:

$ ssh {USER NAME}@{DOMAIN NAME}.com

Assuming you’re in your home folder (i.e. ~/), create a backup folder:

$ mkdir backup

We’re going to use that to backup the WordPress uploads folder, as well as automatically backup our database on each deployment.

Copy your WordPress uploads folder into the backup folder:

$ cp -R {DOMAIN NAME}.com/wp-content/uploads backup/uploads

If there are any additional folders that you’d like to backup, follow a similar pattern.

Optionally, if you’d like to backup your database before each new deployment, create a database folder as well:

$ mkdir backup/database

Next, we’ll prepare a new Git repository for deployment:

$ mkdir {DOMAIN NAME}.git
$ cd {DOMAIN NAME}.git
$ git init --bare
$ touch hooks/post-receive
$ nano hooks/post-receive

This should leave you with a text editor open. If you don’t have nano on your webserver, use whichever text editor you’d like. Paste the following into your text editor, then edit to substitute your proper configuration. Keep in mind that the mysqldump section is optional.

#!/bin/sh

# Backup database first, just in case we need to roll back
mysqldump -h mysql.{DOMAIN NAME}.com -u {DATABASE USER} -p{DATABASE PASSWORD} {DATABASE NAME} > {HOME FOLDER PATH}/backup/database/{DATABASE NAME}_$(date +"%Y_%m_%d_%H_%M").sql

# Checkout received push to deploy folder (overwrites everything)
git --work-tree={HOME FOLDER PATH}/{DOMAIN NAME}.com --git-dir={HOME FOLDER PATH}/{DOMAIN NAME}.git checkout -f

You can then press Ctrl+O to write the changes, followed by Ctrl+X to exit the editor. You’ll then have to add execute permissions to the newly created script:

$ chmod +x hooks/post-receive

Server configuration is completed. Type exit followed by a return to exit the remote session.

Step 3: Add the Remote Location to Your Repository

Navigate to your local Git repository, then run this command:

$ git remote add production ssh://{USER NAME}@{DOMAIN NAME}.com/{HOME FOLDER PATH}/{DOMAIN NAME}.git

You can then push your repository to your new remote location; this should trigger a deploy.

$ git push production master

Done!

And that’s it! Now you can just push to your production remote head anytime you want to deploy your repository to your live site. Additionally, you could add additional remote branches to create development, testing, or staging servers and add them in a similar fashion.

As a note, I’ve tested this process on multiple Dreamhost websites and it works very well. You may have to make adjustments depending on your host. Good luck and happy deploying!

Update 01/27/2014: As asked in the comments below by Prasad, there is the concern of WordPress 2.7+ and the new auto-updating system. As per this post on the Make WordPress Core blog, WordPress tries very hard to detect how you’ve deployed your site. If you use any common version control system, it will disable the auto-update feature.

  • http://kidakaka.com/blog Prasad

    This is a great post! Thanks!

    I was looking at deploy.io and other such services … will give this a whirl. A quick question, what happens when WP 3.8 auto-updates? won’t it impact the git records?

    • http://www.brandonmartinez.com/ Brandon Martinez

      It won’t affect your git repository, but if WordPress auto-updates and you republish, you’ll roll back to the same version that’s in your repository. It’s probably best to disable WordPress auto-updating if you’re going to use a VCS-deployment system.

      Also, WordPress attempts to check if you’re running a VCS-based deployment, and if so, disables auto-update: http://make.wordpress.org/core/2013/10/25/the-definitive-guide-to-disabling-auto-updates-in-wordpress-3-7/

  • Raoul

    This is great information; however, you’re backing up the database as part of this process in case of a potential rollback — how do you handle image content? If the site has database information for image content that doesn’t exist, is there a point of rolling back the database in this manner?

    • http://www.brandonmartinez.com/ Brandon Martinez

      Since this is taken as a snapshot right before deployment, it’s really only there so that if for whatever reason your site gets taken down, you can get back to a safe spot. You really shouldn’t be restoring from a backup that’s older than your current deployment.

      If you had to, however, you could always break the SQL output down and restore just the relevant pieces to get back where you were (e.g. the wp_options table).

Copyright © 2006 – 2014, Brandon Martinez. All rights reserved. A Martinez Media site.