The more you do with with WordPress, the more likely it is that your installed codebase is going to stray from the default distribution from WordPress.org. Making minor changes is tempting. There are a lot of forum posts out there asking how to apply minor tweaks, and some of the proposed solutions aren’t always the most forward thinking.
For many years now I’ve been responsible for websites that are powered by Open Source software (Drupal, Magento, and WordPress, primarily). I’ve tried a lot of different ways to manage the integration of updates. One thing I’ve learned is that the longer you wait between upgrading your site, the more work each upgrade is. Keeping on top of changes is important, for a couple of reasons. First, you want to integrate new features and obviously security fixes. Secondly, the less complex each update is, the easier it is to apply and verify that it doesn’t break anything.
Currently, my favorite approach is to use the tools “diff” and “patch,” which are standard on any common UNIX or Linux system. Here’s what I do.
Download the “stock” releases
Go to the website of your open source software and download the latest release. Also, if you don’t have it, you’ll want to download the release of your current install as well. You might have to search for the “release archives” section to find this.
Create a directory to extract these two releases into, and extract each and rename to reflect the release. In this example, I’m going to show an upgrade from WordPress 3.0.1 to WordPress 3.0.4.
you@foo:~/$ cd Projects
you@foo:~/Projects/$ mkdir WordPress && cd WordPress
you@foo:~/Projects/Wordpress/$ tar -zxf ~/Downloads/wordpress-3.0.1.tar.gz && mv wordpress wordpress-3.0.1
you@foo:~/Projects/Wordpress/$ tar -zxf ~/Downloads/wordpress-3.0.4.tar.gz && mv wordpress wordpress-3.0.4
you@foo:~/Projects/Wordpress/$ ls
wordpress-3.0.1 wordpress-3.0.4
Compare the releases
Now is a good time to see what changed between the two releases. You can use the diff command to do this.
you@foo:~/Projects/Wordpress/$ diff -rq wordpress-3.0.1 wordpress-3.0.4
Files wordpress-3.0.1/readme.html and wordpress-3.0.4/readme.html differ
Files wordpress-3.0.1/wp-admin/includes/file.php and wordpress-3.0.4/wp-admin/includes/file.php differ
Files wordpress-3.0.1/wp-admin/includes/plugin.php and wordpress-3.0.4/wp-admin/includes/plugin.php differ
Files wordpress-3.0.1/wp-admin/includes/update-core.php and wordpress-3.0.4/wp-admin/includes/update-core.php differ
Files wordpress-3.0.1/wp-admin/plugins.php and wordpress-3.0.4/wp-admin/plugins.php differ
Only in wordpress-3.0.4/wp-content/plugins/akismet: admin.php
Files wordpress-3.0.1/wp-content/plugins/akismet/akismet.php and wordpress-3.0.4/wp-content/plugins/akismet/akismet.php differ
Only in wordpress-3.0.4/wp-content/plugins/akismet: legacy.php
Files wordpress-3.0.1/wp-content/plugins/akismet/readme.txt and wordpress-3.0.4/wp-content/plugins/akismet/readme.txt differ
Files wordpress-3.0.1/wp-includes/canonical.php and wordpress-3.0.4/wp-includes/canonical.php differ
Files wordpress-3.0.1/wp-includes/capabilities.php and wordpress-3.0.4/wp-includes/capabilities.php differ
Files wordpress-3.0.1/wp-includes/comment.php and wordpress-3.0.4/wp-includes/comment.php differ
Files wordpress-3.0.1/wp-includes/formatting.php and wordpress-3.0.4/wp-includes/formatting.php differ
Files wordpress-3.0.1/wp-includes/functions.php and wordpress-3.0.4/wp-includes/functions.php differ
Files wordpress-3.0.1/wp-includes/kses.php and wordpress-3.0.4/wp-includes/kses.php differ
Files wordpress-3.0.1/wp-includes/load.php and wordpress-3.0.4/wp-includes/load.php differ
Files wordpress-3.0.1/wp-includes/ms-files.php and wordpress-3.0.4/wp-includes/ms-files.php differ
Files wordpress-3.0.1/wp-includes/version.php and wordpress-3.0.4/wp-includes/version.php differ
Files wordpress-3.0.1/xmlrpc.php and wordpress-3.0.4/xmlrpc.php differ
Since the output of this command can be unwieldy, I’ll break it down by grepping the words “Only in” and “differ”:
you@foo:~/Projects/Wordpress$ diff -rq wordpress-3.0.1 wordpress-3.0.4 | grep differ
Files wordpress-3.0.1/readme.html and wordpress-3.0.4/readme.html differ
Files wordpress-3.0.1/wp-admin/includes/file.php and wordpress-3.0.4/wp-admin/includes/file.php differ
Files wordpress-3.0.1/wp-admin/includes/plugin.php and wordpress-3.0.4/wp-admin/includes/plugin.php differ
Files wordpress-3.0.1/wp-admin/includes/update-core.php and wordpress-3.0.4/wp-admin/includes/update-core.php differ
Files wordpress-3.0.1/wp-admin/plugins.php and wordpress-3.0.4/wp-admin/plugins.php differ
Files wordpress-3.0.1/wp-content/plugins/akismet/akismet.php and wordpress-3.0.4/wp-content/plugins/akismet/akismet.php differ
Files wordpress-3.0.1/wp-content/plugins/akismet/readme.txt and wordpress-3.0.4/wp-content/plugins/akismet/readme.txt differ
Files wordpress-3.0.1/wp-includes/canonical.php and wordpress-3.0.4/wp-includes/canonical.php differ
Files wordpress-3.0.1/wp-includes/capabilities.php and wordpress-3.0.4/wp-includes/capabilities.php differ
Files wordpress-3.0.1/wp-includes/comment.php and wordpress-3.0.4/wp-includes/comment.php differ
Files wordpress-3.0.1/wp-includes/formatting.php and wordpress-3.0.4/wp-includes/formatting.php differ
Files wordpress-3.0.1/wp-includes/functions.php and wordpress-3.0.4/wp-includes/functions.php differ
Files wordpress-3.0.1/wp-includes/kses.php and wordpress-3.0.4/wp-includes/kses.php differ
Files wordpress-3.0.1/wp-includes/load.php and wordpress-3.0.4/wp-includes/load.php differ
Files wordpress-3.0.1/wp-includes/ms-files.php and wordpress-3.0.4/wp-includes/ms-files.php differ
Files wordpress-3.0.1/wp-includes/version.php and wordpress-3.0.4/wp-includes/version.php differ
Files wordpress-3.0.1/xmlrpc.php and wordpress-3.0.4/xmlrpc.php differ
you@foo:~/Projects/Wordpress$ diff -rq wordpress-3.0.1 wordpress-3.0.4 | grep '^Only in'
Only in wordpress-3.0.4/wp-content/plugins/akismet: admin.php
Only in wordpress-3.0.4/wp-content/plugins/akismet: legacy.php
So we can see a number of files have been altered, and a couple of files in the akismet plugin have been added. In this release, no files were deleted. If they had been any, we would have see that in the “Only in” portion.
Create a patch file
The next step is to create a patch file so that we can apply these changes to our active codebase. The patch program takes a special diff file and uses it to systematically apply changes to any number of files. The diff file that it uses will indicate which lines to remove, and which to add. When a line is modified, the old version is removed by patch, and the new version is added. Using patch is handy because if there are target files which you have made changes to, your changes will be preserved, unless they conflict with the changes that need to be made by patch. This happens on a line by line basis. It’s for this reason that these tools are so useful when upgrading a codebase that contains little tweaks that you’ve made. You can apply the changes from the upgrade, and preserve your tweaks at the same time.
Here’s how to create the patch file:
you@foo:~/Projects/Wordpress$ diff -rupN wordpress-3.0.1 wordpress-3.0.4 > wordpress-3.0.1_to_wordpress-3.0.4.patch
Apply the patch to your install
Now you need to apply this patch file to your codebase. I wouldn’t recommend doing this on a live site without testing it first in a different environment. I’m applying the patch on my laptop, which is where I do my development. My WordPress codebase lives in ~/Sites/ekmitchell.com/public.
you@foo:~/Projects/Wordpress$ cd ~/Sites/ekmitchell.com/public
you@foo:~/Sites/ekmitchell.com/public$ patch -p1 < ~/Projects/Wordpress/wordpress-3.0.1_to_wordpress-3.0.4.patch
It's on this step that you're going to find out if any of your changes conflict with the changes made to the released versions. I'll leave dealing with that as an exercise for the reader
. If you run into problems, please leave a comment here and we'll figure it out.
If everything goes smoothly, your code has now been updated. Depending on how you manage your development code and your production site, you'll need to migrate your updated code base to your web server.
If you're using WordPress, you'll need to go to http://yoursite.com/wp-admin/upgrade.php to apply any database updates that need to happen. Other software is likely going to have an equivalent step that needs to happen. Refer to your software's documentation for more information.
I hope this post is helpful to anyone managing open source software for websites. I want to thank Stephen Jungles for his post on diff and patch, which I used this morning to refresh my memory.
If you have any questions or problems, please leave a comment below!