Managing projects in git with branches

As I have grown as a developer, the single greatest change I made was switching to using version control. My weapon of choice – as with most developers – is git. The idea of editing a site over FTP now makes me cringe.

Once I got familiar with git, it became apparent that I wasn’t using it particularly well or efficiently. With a bit of research, experience and many issues, I’ve settled on a development workflow which works nicely for me.

The root of it all is branches (pun wholly intended; you’re welcome).

Project configuration

My particular workflow is built around my typical project setup, but it will broadly apply to most people with some additions, omissions and tweaks. I’m a huge fan of WP Engine, not least because it gives you git access as well as a staging site to work with. As such, every project I run on WP Engine has two remotes on the hosting side: production and staging.

Furthermore, because I collaborate with other developers on my projects, I use GitHub (with private repositories) as our central codebase and project management tool. This is then a third remote for my project (I call my GitHub remote “origin”).

With GitHub as our main codebase library, a staging site for client review and a production site in addition to my local development environment using Varying Vagrant Vagrants, I have everything I need to manage a project.

Branch all the things

Branching is an incredibly powerful tool. It allows you to take the current state of your codebase, copy it and make changes to it without affecting the original codebase, meaning that you can develop something while the live codebase for your site remains intact. This way, you can build, test, review, delay, trash and procrastinate without breaking your site. Once everything is built the way you want, you simply “merge” your development branch into your master branch and push it live. Seamless, smooth and robust.

If you’re not yet familiar with branches, trust me that they’re a godsend and you’ll want to use them, so get into the habit of branching as soon as possible. The sooner you can get into a good habit, the easier the transition will be and the more prepared you’ll be for when your projects expand and get more complicated with other developers assisting.

Here’s my workflow. Any time anything needs to be worked on on the site, a new branch is created. This is almost without exception (I’ll make exceptions for fixing typos, adding single CSS rules etc.). Branches are classified into two groups: features and issues. When something breaks, it’s an issue; when something new is wanted, it’s a feature.

Branches are named descriptively for easy reference and are nested into these two groups, so if a client wanted a new home page layout, I’d create a branch called feature/new-home-page:

or if the client came to me and said that his shortcode which displays his age is not working, I’d create a branch called issue/age-shortcode:

GitHub (or whatever git server you choose to use) is where you push these branches if you want to store them or collaborate with other developers on them.

Once you and your colleagues have finished working on the new feature, or fixing the issue, you’re ready to show it to the client for his review. The feature and issue branches that I’ve spoken about so far are development branches, for organising code and collaborating. Now a new type of branch comes in to play: environment branches.

Environment branches

Your local development environment notwithstanding, you’ll have a certain number of other environments for your code. As I mentioned, my typical setup includes a staging site and a production site, each of which is its own environment. These environments should have their own branch which precisely mimics what’s on that site, so in my case, I have a branch called staging and a branch called production.

When you’re ready to add your feature or bug fix to a site, either for your client to review (more likely with features) or to go live (more likely with issues), you need to merge that development branch into the environment branch and then push that environment branch to the remote.

This means that there’s only ever one branch on your staging/production remotes. The reasons for doing this are many, but the main one for me is that you want to be able to push several features or bug fixes to an environment at the same time without waiting for one to be resolved before working on the next one.

Let me show you an example. Let’s say a client wants me to build a new layout for the home page. I create the new home page layout and want him to take a look at it. Meanwhile, he’s asked me to also add Doubleclick for Publishers ad zones to his theme. I build that and want him to take a look at it as well before going live.

If I did all of this on the master branch, it would look something like this:

That works OK, but the issue comes when the client is happy with the DFP integration and wants to go live with it but still needs you to tweak the home page layout. You can’t push master to production because then the new home page layout will be there also and you can’t (easily) push just the DFP changes to production either.

The better way to do it is more like this:

Because each development activity and each hosting environment has its own branch, it’s easy to separate things out and get exactly what you want where you need it. Hopefully this example shows how just two simultaneous development tasks necessitates a robust branching strategy like this.

Using GitHub issues

GitHub is so handy and easy for managing projects. Its issues feature allows you to easily track and collaborate on development tasks with great ease. I open an issue for each task that needs done and use labels to organise them. With GitHub’s ability to close issues from commit messages, it becomes an incredibly powerful tool for managing an entire project.

Your input

This workflow has come about as a result of my own experiences and research but I by no means consider myself an expert on git or development, so I’m very much open to hearing how you develop and what strategies you like you to use to manage your projects. Please contribute your thoughts in the comments below.

18 thoughts on “Managing projects in git with branches”

  1. EL says:

    Curious to hear what the setup should be if I’m not using a host like WP Engine, but rather GoDaddy or similar. I’ve been struggling to set up a dev site but it seems like so much work to refresh!

    1. Well, this is all based around git. Does your GoDaddy plan support git? If not, then none of this will be of any use to you. It’s for reasons like this that I switched to using git and only using hosts that support it, like WP Engine or SiteGround.

  2. EL says:

    Probably not :)
    Oh well!

  3. Austin says:

    I’ve found that using DeployBot to manage deployments from GitHub to both my production and staging servers works very well. DeployBot hooks to your GitHub account and you can set it to automatically deploy new pushes. I use CodeAnywhere (which has git integration) to develop my code on a virtual server hosted by CodeAnywhere. This allows me to work on and preview my program in a totally virtual environment. Then when I finish a part of the code I can commit and push it to my GitHub repository. DeployBot recognizes the push and automatically deploys the code to my staging server via FTP. Once things are verified and ready for production I can elect to manually deploy the code from the staging server to the production server. DeployBot also lets me rollback versions on either production or staging to a previous commit.

    I know it sounds it little complex but it’s a system that works well for me and just wanted to share. After reading this post I realized I need to start using branches with my git repository more. Part of me gets lazy and just sends everything to the Master, but I know I’m just asking for trouble by doing that. Thanks for the great post about branches!

  4. gbell12 says:

    I’ve used Vagrant, but can’t see how the complexity and memory-hoggery of VVV is better than a local LAMP or WAMP stack. Do the benefits mostly come in when you’re working with other people?

    1. VVV has no benefits when working with other people because it’s just your local environment and someone else presumably also has their own local environment (although, you can share virtual configurations, which could be useful for troubleshooting). The main benefit of VVV is that it allows you to run different environment configurations whereas MAMP/XAMPP are typically static and require updating.

  5. gbell12 says:

    Ah, and one more thing… how do you deal with the usually necessary step of database search/replace to change the all the URLs from your dev to staging or production?

    1. Oh, that’s easy. Allow me to introduce you to the wonderful world of WP Migrate DB Pro (although, when deploying to staging/production from dev, I’m only pushing code, not the DB, so no need to use this in that fashion really).

  6. Piet says:

    Hi Dave, I’m also under-using git, so thanks for the article where you lay things out.

    What I don’t understand though is when you start talking about environment branches. Where exactly do the feature and issue branches live then? Or are you saying that each environment has these feature and issue sub-branches? Or do you perhaps merge the feature and issue branches with each environment branch?

    Please clarify if you can.


    1. So, when I have an issue that needs fixing, or a feature that needs building, I branch from master on my local machine. If I need to work with others on it, I’ll push it to origin (GitHub). Otherwise, once it’s ready to review/publish, I checkout staging or production as appropriate, pull the latest changes in from origin (in case anyone else has committed anything) and merge in the issue/feature branch and push the staging (environment) branch to the staging site. The staging and production sites only ever have a single branch on them (staging or master, respectively) and only my local repo and origin will have the issue/feature branches. Once the code is published, I push the final version of the branch to origin (for archiving in case it is needed in future) and delete it from my local repo.

  7. wido says:

    Hi, thanks for the great article. I just started to implement this work flow in my projects. Really useful :D

  8. gbell12 says:

    Once I push to staging, my client starts to populate with content (after all, it’s not ready for production without that too). That means when I need to make changes I need to merge their file changes (and replace my local db). Would this mean that I need to make ‘staging’ a normal (non-bare) repo, and pull/push/merge from it?

    1. Are they making changes to the files outside of git? If they’re just updating the database, pull the database from the staging site to your local site using WP Migrate DB Pro

  9. gbell12 says:

    They’re uploading images as well as editing pages.

    1. Editing pages only affects the database, so that’s not a problem, but are you version-controlling your wp-content/uploads folder? I can’t see a benefit to doing this – it’s your static files that don’t get developed over time, so there’s no sense in adding them to version control.

  10. gbell12 says:

    Editing pages affects both the database and wp-content/uploads, as soon as they hit “Add Media” and upload something. Right? So we have theme code and assets, plugin code and assets, the database, and wp-content/uploads. Lots of things changing for different reasons, with some on disk and others in a database (on disk).

    Then there’s your code and vendor code.

    So, I can’t see how a git workflow with WordPress can be all that clean or convenient… not to mention impossible to merge if I change something on my dev site and they change something on staging. Handshaking is essential.

    If you wanted to version control the whole site (and be able to push publish), putting wp-content/uploads under git’s control wouldn’t be such a bad idea. Doesn’t really matter that older files don’t change.

    Near as I can tell, a conglomeration of WP Migrate DB, git, and composer to manage everything. And in my experience so far, that’s not hugely better than what I do now: schlepping BackupBuddy backups between dev and staging, and making sure only me or the client is making changes.

    1. I still don’t think that your wp-content/uploads folder needs to be version-controlled. Version control is for code that you expect to change over time. wp-content/uploads is a fairly static directory. What I do is keep everything up-to-date on the production site and then pull in the new media to my dev and staging sites using WP Migrate DB Pro. It works well for me, but everyone’s workflow and needs are different.

  11. Piet says:

    Thanks for your reply, but you officially lost me. I probably need a visual help to get what you’re doing… Anyways, your article helped me to be more conscious about branches and I’m trying to use them on a project I’m current working on :)

Leave a Reply