Managing WordPress with Git

In addition to blogging, WordPress can be a great way to manage content for a basic website: what we in the biz like to call, a CMS. I’ve recently been building more websites using WordPress for the backend, and although it’s been relatively easy to manage content, it can be a pain to manage upgrades, plugins and theme customizations over FTP, or directly on the server.

Since I’ve had to do more wordpress development recently, the need to test and backup my customizations has increased. So I decided to set up a local mirror of my blog and put it under source control. I recently read an article entitled Using Git to manage a web site, which lists the steps needed to place your web content under git source control, and deploy that content to the production server over SSH. Using this system, you get two huge benefits just by learning a few git commands.

It would also be nice to be able to separate my customizations and content from official wordpress releases, and merge them in with each new release. A tutorial I found at wp.stackexchange.com (git by example – upgrade wordpress like a ninja) outlines the steps needed to mange this process.

I’ll show you how I use these two tutorials to manage this site. First, you want to set up your local git repository:
$ wget http://wordpress.org/wordpress-3.0.4.zip
$ unzip wordpress-3.0.4.zip
$ cd wordpress/
$ git init
$ git add .
$ git commit -m'check in initial 3.0.4 upstream'
$ git status

On my dev machine, I grab the same version of version that my blog is currently running on, initialize the git repo, and add/commit the files.

Next, we need to add all of our customizations (you can skip this step and the one after if starting a new blog or site from scratch) to a separate branch in git:
$ git branch mine
$ git checkout mine
$ rsync -cuvr MY_SERVER:MY_DOCUMENT_ROOT/ .
$ rm -rf stats error phpinfo.php
$ git status
$ git add .
$ git commit -m'added my themes, config and network patch'

Here, I create a branch called ‘mine’ and rsync the live site back to my local working folder. There’s some stuff I don’t need versioned, so I get rid of it. You can also add these files to a .gitignore file. If you don’t have rsync installed, you can ftp your customized WP files instead. If you are familiar with rsync, I reccomend adding ‘n’ to the flags so that you can preview what will be added to your pristine WP install.

Now we need to merge our changes and new files with the latest WP version:
$ git checkout master
$ cd ..
$ wget http://wordpress.org/wordpress-latest.zip
$ unzip wordpress-latest.zip
$ cd -
$ git status
$ git add .
$ git commit -m'check in initial 3.1 upstream'

Here, I go back to the master branch and extract the latest WP code over the existing files. Don’t worry about losing any data since git is tracking the changes.
$ git checkout mine
$ git rebase master
$ git reset wp-content/plugins/akismet/akismet.php
$ git checkout -f wp-content/plugins/akismet/akismet.php
$ git add .
$ git rebase --continue

In order to merge in he changes from the master branch, I rebase the code on the mine branch and handle the conflicts. The rebase command complained about a conflict in an Akismet plugin file which was changed between the base 3.0.4 version and the 3.1 upgrade. Since I didn’t care about losing that version (I must have updated it through the admin panel), I ended up resetting that file on the branch back to the 3.0.4 version and committing it.  rebase –continue finishes the merge of my customizations and the new 3.1 version in the master branch. I will repeat this process (the last two steps) every time I need to upgrade WP.

The next step is to automate the deployment of any updated or new files to the server. First, we’ll set up a remote repository that will mirror our local one:
$ mkdir WEBSITE.git && cd WEBSITE.git
$ git init --bare

Next, I need to add a script that will pull all updated files from git into the document root and restart the server:

$ vi WEBSITE.git/hooks/post-receive
#!/bin/sh
sudo chown -R MY_USERNAME MY_DOCUMENT_ROOT
GIT_WORK_TREE=MY_DOCUMENT_ROOT git checkout -f mine
sudo chown -R apache:www MY_DOCUMENT_ROOT
sudo /etc/init.d/nginx reload

(Replace everything in CAPS with your info except for GIT_WORK_TREE.)

In order for those sudo commands to run, I need to add these two lines to the bottom of my /etc/sudoers file (use visudo!) as root:
MY_USERNAME ALL=(ALL) NOPASSWD: /bin/chown
MY_USERNAME ALL=(ALL) NOPASSWD: /etc/init.d/nginx

Now, back on my local machine, I can add a remote mirror and deploy the files from my branch with  the git push command:

$ git remote add web ssh://MY_SERVER/home/MY_USERNAME/WEBSITE.git
$ git push web +mine:refs/heads/mine

After the initial push, you only need to type ‘git push web’  for subsequent updates.

Mirroring installations can have some pitfalls, such as accidentally deploying debugging code or special local settings. So I’ve added these lines of code to my wp-config.php file:
if (file_exists('dev_settings.php')) {
include('dev_settings.php');
} else {
$debug_on = false;
}
define( 'WP_DEBUG', $debug_on);

So I throw whatever custom settings into dev_settings.php and then I exclude that file from git so that it doesn’t get pushed up to the live server:
$ echo dev_settings.php >> .git/info/exclude
$ git status

And now you’re a bonafide WordPress-Git-Ninja!

I recommend excluding any user upload files from git and finding a way to back them up separately. The push process won’t remove anything from your doc root, so you can pick and choose which files you need under version control.

Please feel free to correct or suggest anything in the comments below.

Wanna run a WordPress Network on multiple ports?

In order to run your blog at a different URL, you will first need to make this change in your theme’s functions.php file:

remove_filter('template_redirect','redirect_canonical');

Somewhere just after the first line should be fine.

H/T velvet blues: Turn Off WordPress Homepage URL Redirection

If you are worried about negatively impacting your SEO, you can wrap it in a conditional like this:

if ($_SERVER["SERVER_PORT"] == 8888) {
remove_filter('template_redirect','redirect_canonical');
}

Assuming you have Apache setup for multiple ports, or you have a caching server like nginx or varnish in front of your Network (Multisite), you may see an error like this if you access the site on a port than 80 or 443:

'Multisite only works without the port number in the URL.'

To fix that, you just need to modify wp-includes/ms-settings.php as described in WP trac, like this:

@@ -26,18 +26,8 @@
if ( !isset( $current_site ) || !isset( $current_blog ) ) {
+        $_SERVER['HTTP_HOST'] = preg_replace( '|:\d+$|', '', $_SERVER['HTTP_HOST'] );
$domain = addslashes( $_SERVER['HTTP_HOST'] );
-        if ( false !== strpos( $domain, ':' ) ) {
-               ....
-                        wp_die( /*WP_I18N_NO_PORT_NUMBER*/'Multisite only works without the port number in the URL.'/*/WP_I18N_NO_PORT_NUMBER*/ );
-                }
-        }

Not that hard, right?

So, you want to make a WordPress theme? Part 1

Setting up your own blog couldn’t be easier these days… that is if you are an experienced internet user or anyone under 35. You register an account at Blogger or WordPress.com and… voila, off you go. For everyone else, a little hand holding and/or coding by a professional is required. This blog’s primary purpose is to share web development and consulting expertise with the community, as well as to inform existing and future customers about the latest technologies and services that I provide. Since I had to get a site up pretty quickly after switching to a new hosting company, I decided to use a self hosted version of WordPress for the webxl.net “backend”, also known as a CMS or Content Management System. In the interest of time, I purchased a professionally developed theme from Themeforest, but I really wish I could have designed one from scratch. A highly customizable one that I could use on my clients’ WordPress projects.

Unfortunately, building a theme from scratch is almost as hard as building a static website from scratch, if not harder, because it needs to hook in with the blog software’s API, in addition to coding the PHP, HTML, CSS, Javascript, slicing up images, yadda, yadda. Only if there was a template to jumpstart the whole process. Enter Automatic’s featured Toolbox theme. Once the WP blog is setup, you just navigate to the appearance section of the admin console, click on Install Themes, click Featured, scroll down a bit to the Toolbox 1.0 theme, and click Install. You should see something like this:

The theme is now installed, which means it has been added to the list of available themes you can activate for the viewing public. At this point though, just click Preview to see the utter horror your blog could become. Don’t worry… in the next installment I’ll show how a tiny bit of CSS can spruce things up, so you can be on your way to building a unique website.

Out with the old…

A new site for the new year. I recently decided to switch web hosts from MediaTemple to Linode, and due to family obligations and a full work load, neglected updating the site for a while, but it’s finally ready to see daylight. The site is now powered by WordPress and a professional theme by valendesigns. Please let me know what you think of the changes in the comment section below.