Text Post

Managing and deploying Wordpress with Git

I would like to document the steps I took to set up a local development version of Wordpress using Git and how I use git to deploy changes to my staging server.

I hope this will be of use to other people or that someone can point out how to improve my current setup.

A local development version of Wordpress under Git

I followed David Winter’s tutorial. This setup gives me the possibility to keep themes and plugins under version control, while having a reference to the core Wordpress package and allowing me to update it with each new release. Here is a quick overview of the setup.

We create a new project folder.

mkdir mysite && cd mysite
git init
touch README.md
git add README.md
git commit -m "Initial commit."

We add Wordpress as a submodule to the project and checkout the last version.

git submodule add git://github.com/WordPress/WordPress.git wordpress
git commit -m "Add Wordpress submodule."
cd wordpress
git checkout 3.6
cd ..
git commit -am "Checkout latest Wordpress version"

We will not be touching the Wordpress submodule, we will only update it when a new version is released. Therefore, we will have to put our configuration and custom development (themes & plugins) outside the Wordpress folder.

cp wordpress/wp-config-sample.php wp-config.php
cp wordpress/index.php .
cp -R wordpress/wp-content .

# you can delete unused plugins and default themes
# example : rm wp-content/plugins/hello.php

git add .
git commit -m "Moving config and content outside the submodule"

We will have to make some changes to these copied files so that Wordpress still finds all the necessary files.

In index.php change

require('./wp-blog-header.php');

to

require('./wordpress/wp-blog-header.php');

and in wp-config.php add the following lines :

define('WP_SITEURL', 'http://' . $_SERVER['SERVER_NAME'] . '/wordpress');
define('WP_HOME',    'http://' . $_SERVER['SERVER_NAME']);
define('WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'] . '/wp-content');
define('WP_CONTENT_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/wp-content');

If we want to use different database credentials for the local development server and the online production or staging server, we can modify the database settings in the wp_config file like this :

if ($_SERVER['REMOTE_ADDR']=='127.0.0.1') {
    define('WP_ENV', 'development');
} else {
    define('WP_ENV', 'production');
}

// MySQL settings - You can get this info from your web host //
if (WP_ENV == 'development') {
    define('DB_NAME', 'mydb-dev');
    define('DB_USER', 'root');
    define('DB_PASSWORD', '');
    define('DB_HOST', 'localhost');
} else {
    define('DB_NAME', 'mydb-prod');
    define('DB_USER', 'username');
    define('DB_PASSWORD', 'pasdword');
    define('DB_HOST', 'mysql.mysite.com');
} 

Finally we commit these changes.

git add .
git commit -m "define correct paths in config files"

Now we can work on our custom themes and plugins outside the core Wordpress folder and keep a record of it in Git. The website should display as normal on our local development server.

When a new Wordpress version is released, we can update the core Wordpress files by using these commands :

cd wordpress
git fetch --tags
git checkout 3.7
cd ..
git commit -m "Update Wordpress to version 3.7"

Deploying changes to a staging server

I followed Philip Brown’s tutorial to let me push local changes to my staging server with a simple command.

We will be creating a Git repository on the same server that hosts our staging version of the website. Each time we push a change to the git repository, the repository will automatically update the code on our staging server.

This means you have to be able to SSH into your server and create a git repository from the command line. Check with your hosting provider if your hosting plan allows this. Here is a quick overview of the setup.

First SSH into your server and create a bare Git repository for your website.

mkdir git && cd git
mkdir mysite.git && cd mysite.git
git --bare init

Now that we have a repository to push to on the server, we can add this as a remote to our local repository. Execute the following command on your own computer, in your local website folder. Don’t forget to change the hostname and path to the correct values.

git remote add origin name@123.456.789:/git/mysite.git

Next we can run the following command to push our code from our local machine to the server:

git push origin master

Now if we have a look at the git log of the server’s repository, we should see that our code has been pushed to the repository.
Because this is a bare repository without a working tree, your code won’t actually be visible outside the log.

If we get a prompt for our password each time we push to the remote server, we can remove this hassle by setting up SSH keys. You can follow these instruction to set up SSH keys.

Finally we will automate the updating of our live server after each push to the git repository. We need to set up a post update hook. Go into your bare repository, then into the hooks directory and create a new script.

// Create a new file
vim post-update

// Copy this text and save the file
#!/bin/sh
export GIT_WORK_TREE=/path/to/you/live/files
git checkout -f

// give the post-receive file execute rights
chmod +x post-update

Now if you go back to your local code, make a change, commit the change and push it to the origin you will see your code magically update.

There is only one problem : since we made a bare repository, the automatic checkout will not update submodules. We will have to manually upload the core Wordpress folder. Also, each time we update Wordpress to a new version we will have to manually upload the new version of the core files to our server. If you have any tips to improve this situation, please let me know.

References