If you have developed WordPress sites for clients this process might sound familiar to you:
After lots of trial and error, I have come up with a process that is more efficient, and allows rapid development of wordpress sites. I use Git, Git Submodules, and WordPress child themes to get going quicker and keep code up to date with minimal effort. (If your not using a revision control system like Git or SVN for development, then check out this funny question and answer session on Stack Overflow Update: Stack Overflow moderators removed the question… bummer. Check out the funny-ness in the wayback machine internet archiver instead)
For this rapid WordPress development cycle, you will need to have Git installed.
The wordpress core dev team uses SVN to manage wordpress development. But I want to use Git for speed and easy branching. Fortunately there is a great WordPress git clone that is updated every fifteen minutes. To get the most recent version of WordPress, simply clone that repo to your project directory.
mkdir projectA git clone https://github.com/markjaquith/WordPress.git ./projectA cd projectA git checkout origin/3.2-branch
Now you have the most recent version of wordpress, and it will be easier than ever to upgrade wordpress and revert if something goes wrong. But we will get into the upgrade process later.
To help get your new WordPress project off the ground, let’s get a quality blank theme that updates regularly. I usually use the Roots theme, which is a quality HTML5 wordpress theme that updates regularly. To make sure our theme stays up to date with the latest wordpress updates, we will add the Roots theme as a Git Submodule. This allows us to essentially add a git repository inside of another repository. Why do this? Because we can update our theme code to the latest release with a simple Git command, instead of downloading and merging on our own. To add the sub-module, change to your project directory and add the sub-module to the themes folder then initialize it:
cd projectA git submodule add https://github.com/retlehs/roots.git ./wp-content/themes/roots git submodule init git submodule update
Update: I have now forked mark’s wordpress git and added roots as a submodule. You can simply clone or fork my repo to save a step. Get it here: https://github.com/clintberry/WordPress Make sure to clone recursive to get the roots theme. This repo updates nightly to the latest wordpress and roots release.
Now you have a quality blank theme installed into your git repo as a sub-module.
Since we have added the new blank theme as a git submodule, we don’t want to edit that theme directly. This could cause problems when/if we want to update our code base for the theme. To better avoid update problems, we can use the often-under-utilized-wordpress feature called child themes. Child themes allow you essentially “inherit” all the functionality of a “base” theme. In this case, we will create a child theme “MyTheme” that will have access to all the functionality of our base theme “Roots”.
Creating child themes in wordpress is simple:
/*
Theme Name: MyProject
Theme URI: http://clintberry.com/
Description: Roots Child Theme
Author: Clint Berry
Author URI: http://clintberry.com
Template: roots
Version: 0.1.0
*/
@import url("../twentyten/style.css");
Take notice of the “Template: roots” field. That is what lets WordPress know that this is a child theme and to inherit all of the roots functionality. Also since this style.css file overwrites the roots css file, we import the css file from roots.
Now you can start your theme development with an HTML5 bang! Child themes make it much easier to get started and even keep your file structure a big cleaner.
Yes, you could update WordPress in the admin panel, but you want to do it in a much cooler, easier-to-revert way. With Git, now you can. First, backup your database. Then in the root wordpress directory, update your Git repo by using git fetch:
git fetch origin
Now merge in any updates from your current branch, or merge in a new branch altogether. This command merges the latest update from the 3.2 branch into your WordPress install:
git merge origin/3.2-branch
Now you have the most recent version of WordPress. It is a beautiful thing.
Don’t worry! If it breaks something, it is easy to go back. First enter:
git log
This will output the most recent changes to your repo. Look for your last change which was merging. It will have a line like this:
Merge remote branch 'upstream/master'
Take the commit sha (the long number right after the word commit) that is located on the commit before the Merge line. Take that sha and enter the command:
git reset --hard your_sha
Now restore your database and you are back in action.
Deploying a WordPress site has always been a thorn in my side. Currently, I am developing a plugin for much easier deployment, but for now things are a bit hairy. The nice thing about git is keeping your code base up to date is much easier. Unfortunately, Git doesn’t help much with the database side of things, so we will focus on just the code base for now.
Deploying with Git Clone is the easiest way to get your code installed on a different server. All you have to do is push your repo to a remote repository (like github) and then clone it directly on the live server. This allows easy updating in the future as well since a simple git pull is all that is required to get the most recent code base. If you don’t have SSH access or if the server you are deploying to doesn’t have Git, then this method won’t work.
For a good guide on deploying the old fashioned way, as well as deploying the database, see This Post
I hope this helps getting your WordPress sites off the ground quicker and easier! As always, any comments or suggestions are welcome.
Damon / August 3rd, 2011 17:03
Hi Clint,
Great article and very helpful. I’m still kinda new to Git and concepts involved, and I think part of my problem is I’m trying to avoid command line. I forked your repo: https://github.com/clintberry/WordPress because I would love to implement the same workflow, but I can’t figure out how to update WordPress and the Git submodule for Roots with my recent fork in the GitHub app. I’m not even sure if I’m on the right WordPress branch in the GitHub app, because I’m not too sure how to switch branched in the app. Do you the app at all, and could you give a few tips on how to update please?
Article was very timely for me, because I was looking to expedite the same workflow in my everyday WP dev affairs. Thanks!
Clint / August 3rd, 2011 17:58
I didn’t get into the nitty gritty of git this time, and I probably should have since it is supposed to cater to people getting started. I have only done command-line, but I downloaded the app to see if I could answer your questions, and I had some trouble, so I probably can’t help you much there. But here are answers to your questions if you use your terminal.
git clone http://your-github-fork-url --recursiveThe –recursive tag makes it check out the roots theme as well
git checkout origin/3.2-branchgit remote add upstream https://github.com/clintberry/WordPress.gitNow you can fetch the updates from my repo with this command:
git fetch upstreamand then you can merge the most recent changes to the branch into your code:git merge upstream/3.2-branchor when they release 3.3, you would use this:
git merge upstream/3.3-branchLast thing you have to do is push it back to your “origin” or your fork:
git push originI hope that helps
Damon / August 4th, 2011 14:44
Thanks Clint, and very helpful. Mainly an exercise that taught me two things: 1) stick with the command-line to learn more fundamentals, 3) UI/apps are nice, but not necessarily the best way to learn to use Git. I’m going to stick with your original instructions in the post, but I did try your comment and it did work, but it is just creating a few extra steps for me. Also, makes me rely on your repo for updates when I can just go straight to the source: WP and Roots. BTW – your Magento post was perfect too as I was just recently trying to install local instance, but running into /hosts file issues, which I’ve resolved thanks to you +2
aaron / November 18th, 2011 13:03
Damon, this statement “my problem is I’m trying to avoid command line” made me cringe. I am very glad for your benefit that you have embraced the command-line. GUI tools are good for GUI things, like design. But you can can be much more productive knowing tools like: wget, ssh, scp, tar (“tar zcvf a_dir.tgz wp-content” a simple quick way to backup a dir), even ssh’ing into a site to download latest.tar.gz from wordpress.org and uncompressing on the server (instead of FTP’ing up) can save 10 minutes or so. Even knowing Vim comes in handy often even if you prefer Textmate (or the like).
Anyway, command line tools (Unix in general) are tools that developers should be familiar with.
Clint, thanks for the post. I didn’t know that WP was on github. My “steps” of development probably just changed.
Casey / December 21st, 2011 1:42
I’ve been looking for the best git/wordpress workflow for my theme development and a good starter theme to make my job easier. So far this has been the most straight-forward guide I’ve come across. I’ve not used root but will definitely check it out.
Eddie Monge / January 23rd, 2012 1:14
You missed talking about using post-commit hooks with services like Github or Bitbucket to automatically update the live site with this type of workflow.
Clint / January 23rd, 2012 15:56
@eddie – Thanks for the suggestion. That is a big time saver and I love git-flow setup with hooks to push to live. With wordpress, however, I find that many things I do require database changes and having automatic pushes to production sometimes wouldn’t work. Do you have any suggestions for that?
Julien Gobi / February 5th, 2012 0:57
Hi!
I also use child-themes and GIT in my workflow. Thanks for the submodule tip, I didn’t know about it!
I was looking for a GIT deployment plugin to avoid the ‘git pull’ phase on the staging server or the live server to make deployment easier.
Let me know if you know one or are interested to build one
I’m also interested to know database sync tips. Specially, how to correct the images URLs in posts when moving frequently db on 3 different domains : local > staging > live ? Currently I do a search and replace in the sql dump…
Clint / February 5th, 2012 3:19
@Julien – Funny that you mentioned a git deployment plugin. A friend and I have been thinking about that and how we would build it.
As far as deployment goes, we do the same thing as you, a search and replace on the sql dump. We do have it automated through a deployment shell script, though. We are also looking into Capistrano. I’ll message you if we make any progress.
mgiulio / February 13th, 2012 7:13
Very, very useful informations, thank you Clint!
Brandon / April 19th, 2012 2:34
Thank you Clint for providing this useful resource. It will increase my productivity and share with others how to improve their WP deployments.
Geert De Deckere / May 9th, 2012 5:56
Useful article, Clint. Is there a special reason you prefer to checkout the branch of the latest stable version? How does that work with subversions like 3.2.1?
I’m using the version tags to checkout exactly the desired version. There’s no need to do merges then neither.
git checkout 3.3.2Clint / May 9th, 2012 14:08
@Geert – Checking out a tag would be better. Thanks for pointing that out! But if you check out a tag directly, it usually puts you in headless mode, so you will need to make your own local branch if you want to keep track of changes. I will update the article.
Geert De Deckere / May 13th, 2012 18:20
Hi, Clint. I thought I’d let you know that after some more trial and error and googling I actually found an easier approach. You can totally avoid setting up themes and plugins as submodules and just give WordPress its own directory. The key is to move the “wp-content” directory outside the “wordpress” directory.
http://davidwinter.me/articles/2012/04/09/install-and-manage-wordpress-with-git/
http://markjaquith.wordpress.com/2011/06/24/wordpress-local-dev-tips/
Clint / June 5th, 2012 16:47
@Geert – That is a good method! I have actually migrated to a different method as well. I am using Vagrant to match my dev environment to the environment that wordpress will be installed on. It has been working great and I will add a blog post soon.
Dan Course / July 13th, 2012 9:34
Hi Clint,
How are any database changes handled when you run the git “git merge origin/3.2-branch” command on the server? Does it make them on the next wordpress load?
Thanks,
DanC
Clint / July 13th, 2012 15:33
@Dan – Yes, just like when you install a new wordpress code-base and link it to an older database, it TRIES to update it, and usually works fine. I have had instances where the upgrade didn’t go smooth, maybe because the versions were too far apart. I would hesitate to upgrade to major revisions, unless I tested it first. Hope that helps.
Robin / August 8th, 2012 14:20
I know not the best solution, but this plugin is great for backing up the database to be ready for move to staging server, etc: serializes it for the new url.
http://wordpress.org/extend/plugins/wp-migrate-db/
Also I use the actual wordpress repo to clone: https://github.com/WordPress/WordPress
Clint / August 8th, 2012 14:30
@Robin, that is a great solution. Also, I didn’t know wordpress had an official github clone, which they probably didn’t when I published this post. Thanks for the heads up, and I’ll update the article!
Jim Krill / August 21st, 2012 21:30
Clint,
This is good stuff. I have just been getting up to speed with git and using it to streamline my production process with WordPress.
Unfortunately, as you have pointed out, there is no easy way to source control the database – at least not that I know of.
For now I am stuck exporting the database everytime it changes and importing it on the development/production server. There is a handy script I found (I think it’s called searchreplacedb2.php) that runs through the db and does a find and replace… and it fixes any serialized data.
If you find any solutions for database syncing, let us know! Thanks again for the article. Glad I came across it.
Kris Z / September 12th, 2012 14:00
Clint.
Great little article.
Deploying the core-theme as a submodule seems easy enough, but how do you later manage the child theme? Do you create yet another submodule, or do you just leave it untracked by git?
Clint / September 16th, 2012 7:01
@Kris – I create a new git project for each project I do. But if you are specifically working on a theme you plan to release, I would just add the theme files to their own git repo. Hopefully that makes sense.
JP / September 20th, 2012 19:26
@Clint said:
“As far as deployment goes, we do the same thing as you, a search and replace on the sql dump. We do have it automated through a deployment shell script, though.”
I’d like to learn more about this deployment shell script. Care to write a blog post explaining how it’s done?
Clint / September 20th, 2012 22:36
JP, in the past I have typically used Phing to deploy PHP projects. I could potentially do a post on deploying wordpress sites with phing. That might be useful
Until then, here is some info on doing a search and replace for serialized DB data from WordPress: http://interconnectit.com/124/search-and-replace-for-wordpress-databases/
JP / September 21st, 2012 18:02
sounds like an e-phing good idea
Jose / January 9th, 2013 15:25
Why the line:
@import url(“../twentyten/style.css”);
in the newly “style.css” file of the child theme???
I thought you were importing the “style.css” file from the roots theme…
Charl Immelman / April 5th, 2013 10:35
Instead of normal Submodules, you could could use Fake-submodules for the child theme. I actually wrote a post explaining how. I used the Bones theme as an example, where one would simply edit the theme itself instead of creating a child theme, then periodically merge in the updates and gracefully fix conflicts.