My Dev Setup, part 4: Version Control and Deployments with WordPress

In an earlier post, I promised to shed some light on our git workflow for WordPress projects. The above image sums it up pretty nicely, but read on for the details.

Most of the development we do happens in a local Apache + PHP + MySQL environment, using MAMP Pro. That means I have a local copy of each site I’m developing, which creates some overhead compared to everyone just working on a central dev server. It’s worth it though because it makes working on different features and code branches easy.

Repository structure

Every project has its own git repository, which we set to the WordPress root directory. This is because most of our projects involve a combination of custom themes and plugins, and it makes sense to group them in a single repository. We still don’t want any of the core WordPress code in git, so we use a .gitignore file based on this excellent template by Joe Bartlett:


# This is a template .gitignore file for git-managed WordPress projects.
#
# Fact: you don't want WordPress core files, or your server-specific
# configuration files etc., in your project's repository. You just don't.
#
# Solution: stick this file up your repository root (which it assumes is
# also the WordPress root directory) and add exceptions for any plugins,
# themes, and other directories that should be under version control.
#
# See the comments below for more info on how to add exceptions for your
# content. Or see git's documentation for more info on .gitignore files:
# http://kernel.org/pub/software/scm/git/docs/gitignore.html
# Ignore everything in the root except the "wp-content" directory.
/*
!.gitignore
!wp-content/
# Ignore everything in the "wp-content" directory, except the "plugins"
# and "themes" directories.
wp-content/*
!wp-content/plugins/
!wp-content/themes/
# Ignore everything in the "plugins" directory, except the plugins you
# specify (see the commented-out examples for hints on how to do this.)
wp-content/plugins/*
# !wp-content/plugins/my-single-file-plugin.php
# !wp-content/plugins/my-directory-plugin/
# Ignore everything in the "themes" directory, except the themes you
# specify (see the commented-out example for a hint on how to do this.)
wp-content/themes/*
# !wp-content/themes/my-theme/

view raw

.gitignore

hosted with ❤ by GitHub

The above means that in practice the contents of a typical project repository structure looks somewhat like this:


/
+-- wp-content/
    |-- plugins/
    |   +-- custom-plugin/
    |
    +-- theme/
        +-- custom-theme/

Sharing code and automated staging with Beanstalk

When I want to share code with my colleagues or am ready to something to a client, I do a git push to a central repository hosted on Beanstalk. Beanstalk has loads of useful features, but the best thing about it has to be the simple deployments it offers. For all projects, we set up automated deployments to a staging server, where we have copies of each site. Deployments to production are also set up in Beanstalk, but (intentionally) require a manual click in the web app.

Going to production

Finally, moving from staging to production can require some tricky search-and-replacing domains and absolute paths in the database. WordPress in Network mode tends to be particularly keen on saving the site URL in way too many places. One way to do this is to perform a search and replace on a SQL dump, but we use this nifty tool by Interconnect/IT, because it correctly handles serialised strings, which are often used in WordPress for things like widget options etc. The same tool is useful when doing the reverse, ie. creating a local copy of an existing site.

Relevant links:

13 responses to “My Dev Setup, part 4: Version Control and Deployments with WordPress”

  1. […] I’ll be expanding on how we use Git in WordPress projects in a later post. […]

    Like

  2. Great post, thanks! And the others from the workflow tools series. Very nice! I’m using these tools, too and after reading your workflow posts installed couple of new apps, like the better touch tool and wp-cli to give it a try.

    Like

    1. Daniel Koskinen Avatar
      Daniel Koskinen

      Thanks for the feedback! I’m glad to hear the posts have been useful.

      Like

  3. Hi, I was looking for the workflow like the one you show here (strangely nobody actually shows it, just talks about it) I am very new to this Version control stuff, I have tried working locally before I gave up and just work on live server since my work is not that complex(I know it’s a no no). I always want to do it the right way–so happy I found your post–it is like a early birthday gift!! but I digress.

    Anyway, you mentioned “search and replace on a SQL dump”using tool by Interconnect/IT when you deploy to a production server (I assume it’s the site you deliver to client) You are saying that you still have to do search and replace before you hit the click button for deployment, correct? I hate dealing with database stuff, it is very mysterious to me–I can’t see it–follow steps but no idea what it does.

    Can you not have the staging server, I thought that was what version control for?

    Thanks
    PJ

    Like

    1. Daniel Koskinen Avatar
      Daniel Koskinen

      @pleelayuvat: search and replace only needs to be done when we’ve finished main development and we’re ready to publish a new site, if the content has been originally input on the staging site.

      The staging server is useful for letting the client try out the site before going live.

      Like

  4. Thanks a million for this post 😉

    I am actually using a quite similar flow with git. Most of my projects are based on yii, and some on other specialized php frameworks such as prestashop.

    For prestashop for examplo, I am also using a quite restrictive .gitignore, keeping track only of the custom themes and plugins I develop.

    Now that I am about to start a wordpress project, I started browsing the web and come to Joe’s .gitignore on one hand, quite inline with my strategy in prestashop, but on the other hand I found some posts suggesting to only ignore a couple of folders!!!

    I am wondering what’s best from deployment perspective.

    including only themes and plugins under git version control, implies that you should start by having a working version of wordpress in the remote site. From that point you can deploy your customizations
    Including everything under version control allows to deploy a full site with one command and some “post deployment hooks” to create, configure and populate the database which is great, but on the other hand is a hassle when you need to update the core files, install new 3rd party plugins, etc…

    I am basically looking for well reasoned arguments in one or another direction 😉

    Like

  5. Great post,

    The main issue I’m having is how to maintain the database between myself and my team. We all have local copies of the WordPress project we are working on, but all of our local machines have their own respective databases. To make that worse, my web host doesn’t allow for remote SQL connections.

    So what could I do? I am very new to version control/deployment and am very eager to learn. However, I’m primarily working with WordPress projects.

    What are your suggestions?

    Thanks!
    J.C.

    Like

    1. Hey, did you find a solution to this? I’m looking into something called WP Migrate DB, which allows you to push / pull the db.

      Like

    2. Yeah, I actually hosted the database in a shared Dropbox folder between myself and my team. This took a little tinkering around with MAMP, but after about 30-45 mins setup time, it worked like a charm. Not the most ideal solution, but it got the job done when I was in a bind because of my host not allowing remote connections.

      Like

  6. Wow. This is great. Combined with Chris Coyiers video tutorial. I have a decent workflow set up!

    Does your staging and production each have their own db? I’m trying to determine how I should set up the dbs here.

    Like

    1. Daniel Koskinen Avatar
      Daniel Koskinen

      Yes staging and production do have their own databases. My colleagues have been looking into WP Migrate DB, which seems like a good solution for easily getting a local copy of production.

      Like

  7. Great post. I have a similar setup myself.

    The one thing that I find difficult with this setup is sharing within a team. Since none of the core WordPress files are in GIT, then cloning the repo will only clone the theme and plugin files and so, from a clone, they won’t have a complete working site.

    How would they quickly go about getting up and running for local development from a clone of just the theme and plugin directories?

    Cheers

    Like