Our Git Flow

One of the more critical processes for a software engineering team is the team’s git flow. The git flow defines what code goes where, and helps add clarity for how code goes through each step of the release process. A strong, well followed git flow will help a team operate efficiently; while a less optimal flow can get in the way and cause more work for everyone involved. We’ve taken some time to better define our git flow for ourselves, and thought it might be helpful for others thinking about their processes and flows.

Priorities of our Git Flow:

For our Git Flow, there were a few priorities we wanted to keep in mind:

  1. We work in mobile — The reality is most of what our Product Engineering team does is in the mobile clients (iPhone and Android), which means our distribution model is based on discreet app store releases rather than the constant deploy of the web. Our git flow needs to be built around the reality of releases.
  2. We don’t know when projects will ship — This should resonate with most engineers reading the article: as an industry we are not good at time estimation. Correction: we are terrible at time estimation. When we start a project, we don’t know when it’s going to ship, or what other projects its going to ship with. We need a git flow that allows projects to stay independent in git, so they don’t block other finished projects from shipping.
  3. We don’t want to keep track of every change — At the other end of the spectrum from big projects that are tough to estimate are the smaller, isolated projects that can be slipped in to any release. These are the small crash fixes that slipped through testing, copy and design optimizations, or minor support requests. We can crank through fixes like this quickly, and don’t want to have to keep track of them all to make sure they get shipped. We need a place for these fixes to live to make sure they go out in the next release without having to think much about it.
  4. We want to keep our merges small, rather than large and unwieldly — We’ve all been there. We feel good about our code, everything works great… and then comes the merge. You spend more hours in your git diff tool of choice trying to litigate every line of code for your project and how it relates to someone else’s… it’s a pain. Our flow is set up to eliminate the mega merge as much as possible. Instead, we err on the side of smaller, more frequent and timely merges.

The three types of branches:

Now that we’ve established our priorities, what’s the git flow? The easiest way to talk about our git flow is to define how our branches are set up. With a detailed understanding of each branch, the code that goes in it, and how that code moves from one branch to another to eventually being released, you’ll have a good sense of our entire git flow.

Master — You can’t talk about git flows without a strong definition for what’s in your master branch. For us, master represents completed, ready to ship work. As we finish work (and by finish I mean it’s tested, pixel pushed, and approved), we push the code up to master. Master should always be in a state ready for the release process to begin, and when we decide we want to start the process we make a Release Branch.

Release Branch — A Release Branch is branched off of master once the Product team has decided there is enough work completed in master that it warrants a release. Release branches are named after the version number they represent, and kick off everything we need to do to release: beta testing, manual regression, crowdsourced testing, etc. As final changes are made to the release, changes are made on the Release Branch and merged back in to master regularly; this ensures minimal merge conflicts, and that anyone working off master has the latest and greatest from the upcoming release. We DO NOT merge master in to the Release Branch; anything pushed to master after the release branch is made waits for the next release.

Feature Branch — Despite being last on the list, this is most commonly where engineers are working. Feature Branches (also sometimes referred to as Epic Branches) represent something being actively worked on. Sometimes this could be a small enhancement that takes one engineer less than a day, other times its a major engagement spanning a team of engineers across multiple weeks. Feature branches are great because it allows us to coordinate a dependency without dictating it’s release or timeline. Whether different parts of the feature are functionally dependent on related code, or the Product team wants to batch things in the same release, a Feature Branch ensures the code is isolated.

A Feature Branch is only merged in to master once it’s been signed off and is ready for a release. In order to ensure that merge goes as smoothly as possible, developers merge master into the Feature Branch often. Often, if a Feature Branch represents a larger feature across multiple engineers, individuals will temporarily make their own branches off the feature branch while they’re working. This can be tough to visualize, but this image should help:

The biggest risk to a feature branch (and developer branches off of them, for that matter) is having too many branches and having them get lost in the shuffle. As a general rule, we make sure all developer branches are merged back into a feature branch at the end of any sprint. Teams are rarely working on more than one or two feature branches at a time; a feature branch should be merged to master as part of getting something complete before moving on to new work.

As you might have noticed, there is no “development” branch like you might see in other git flows. We simply haven’t found the need for this branch. We use git tags to identify the latest release / what’s in production. And while web development teams may have hooks with pushes from development to master that will push code to production, that process is more involved and starts outside of git in our mobile world.

That’s about it. While these types of branches may seem simple, it allows us a nice balance of organization and flexibility when it comes to release time. Full disclosure — like any git flow, this one has it’s pros and cons. Our flow has evolved over the past year as we’ve grown, and in truth, this article stems from some confusion we had recently about our git flow. If you have a better flow, or tips on how to improve ours, we’d love to hear it! While we feel comfortable with this flow, we know there’s always ways to improve it.