ENV Branching with Git

Posted in Insights

Another Successful Branching Model

When developing applications with multiple features, team members and deadlines, a version control system with robust branching is key. This is why we switched to Git from SVN over four years ago. After taking a simplistic approach we quickly realized our branching model needed another look to allow for development of concurrent features.

When asking most people what the ideal branching strategy is I get pointed to A successful Git branching model, also known as git-flow. While tried and true, there’s one element that didn’t line up with the majority of our applications: releases. More on that later.

Without releases, this model becomes overly complex. Instead of adopting unnecessary complexity, our team built off of our simplistic approach, adding steps and methodologies as needed. Each addition to the process was discussed, used in the wild for a couple weeks and rediscussed, ultimately keeping it or cutting it. We stumbled at times, but eventually we came up with a strategy that’s flexible enough for our client demands, yet more simple than most models. We've dubbed it ENV Branching.

The Basics

ENV Branching is based on the environments the application deploys to. For us these are typically:

  • production: the live site
  • stage: for staging features to the client
  • development: for staging features internally

Each environment has a dedicated ENV branch: master, stage and dev. At any given time, those branches will resemble exactly what’s on their corresponding environment. All commits are done on a feature branch and merged into the environment you wish to deploy. With continuous integration, pushing an ENV branch to the remote triggers an automatic deploy. When a feature is ready for production a pull request is created to merge the feature branch into master. Approval and merge of the pull request triggers an automatic deploy to production.

The Rules

To maintain the integrity of the branches and ensure we can deploy features independently we follow these rules:

  1. NEVER commit directly to an ENV branch (master, stage or dev)
  2. NEVER merge one ENV branch into another
  3. Feature branches should be autonomously deployable

A Simple Example

[]

  1. create your feature branch

    # grab the latest from origin/master
    git pull --rebase origin master
    # create your feature branch
    git checkout -b 123-wine-validations
    
  2. commit your changes

    # stage and commit your changes to feature branch
    git add -A
    git commit -m "refs #123 - adding validations to wine model"
    
  3. deploy changes to dev for internal review

    # rebase from origin/master and resolve any conflicts
    git pull --rebase origin master
    # switch to the dev branch
    git checkout dev
    # rebase from origin/dev
    # (which could contain merged branches from other team members)
    git pull --rebase origin dev
    # merge your branch
    git merge 123-wine-validations
    # push changes to origin/dev (which triggers a deploy)
    git push origin dev
    
  4. deploy changes to stage for client review

    # checkout your feature branch and rebase from master
    git checkout 123-wine-validations
    git pull --rebase origin master
    # follow the previous step only using the stage branch
    git checkout stage
    git pull --rebase origin stage
    git merge 123-wine-validations
    git push origin stage
    
  5. deploy changes to production

    # checkout your feature branch and rebase from master
    git checkout 123-wine-validations
    git pull --rebase origin master
    # push your branch to origin
    git push origin 123-wine-validations
    # open a Pull Request to merge feature branch into master
    # or merge it to master manually
    

Why We Like It

Simplicity. In the same vein as the programming methodology, we like to Keep It Simple, Stupid. No matter how solid your branching model is, if people misuse it due to complexity it's not working.

Even though it’s simple, it maintains the power of more complex models. ENV branching allows us to develop and stage concurrent features without blocking each other or waiting for a release to deploy.

The cherry on top is that it works perfectly with our continuous integration system. Since we have a branch for each of our environments, we can trigger tests and a deploy when one of the ENV branches are pushed.

When Not to Use It

If your application has structured releases that need to be tagged and individually maintained, by all means use a model that includes actual release branches.

There were a couple times we tried to gang up features into faux-releases that were merged and deployed simultaneously. Using this model in this way can cause conflicts. However, it’s easy enough to create a release branch to base the feature branches off of as long as it’s not a regular practice.

Are Releases Needed?

Most of the work we do are client websites and single serving web applications. There is only one stable version that needs to be maintained and releases become a method to structure client communication and roadmap features.

We thought faux-releases would aid in our development process, when in reality they were a restriction. Certain features would hold up the entire release while in refinement rounds with the client and other features would go stale. At the same time the client would be anxious to start the next round of features or have a promotion coming up with a hard deadline.

ENV branching gives us the agility to develop a wide range of features simultaneously without being tied to a release schedule. Features are deployed as they are completed, which keeps us our applications shipping and our developers building.

- James Kurczodyna is the Director of Application Technology at FINE.

More Insights