Git Environmentalism - Protect our branches

Our analytics team is maturing. We have our code under version control. We check out branches when developing new features. The team even has code reviews to approve pull requests.

But then the fire drill comes in from the CFO. A couple of people drop everything to put out the fire and commit directly to the master branch in a need for speed.

At that point, all the team can do is step back to see the damage. The first sign of trouble would be the production job fails to build, which kicks off another frenzied commit to master to fix those mistakes. Later on, pull requests from the release branch begin having merge conflicts. These merge conflicts trickle through each team member’s local repo opening the door for more error and confusion.

We know it is not right to commit to the master branch, and it can cause pain for the entire team later. How can we prevent ourselves from doing this to ourselves?

Thankfully GitHub helps us with our branch conservation efforts. GitHub has protected branches.

To be fair, all major git repository hosts have a way to protect branches. I am only writing about GitHub because it is what I use.

A second side note, you will need a paid GitHub account. Branch protection rules are not available in the free version.

Map out your environment

Before we start putting restrictions on certain branches, let us first understand what exists. There are likely implicit assumptions around each branch.

A typical branch pattern is:

  • Master branch - production code
  • Release branch - a staging area for all new code before going to production
  • Feature branch (every other branch) - these are one-off branches that represent one unit of work

Common restrictions put around branches are:

  • Should never be deleted
  • Should never be committed to direct - instead, all new code comes through PRs
  • Should only accept PRs from a specific branch
  • Should restrict who can accept PRs
  • Should require review before accepting
  • Should pass all status checks before accepting

You can line up these restrictions to your branches. Once you have that map, you are ready to set up your protections.

Enact Branch Protection Policies

To find where we can set our protection rules, open the repository, navigate to Settings, then open the Branches section. From here, we will add rules for each branch.

Matching your branch 🧩

The “Branch name pattern” box allows us to isolate the protections to specific branches. Using our simple branch pattern of master ← release ← feature, we will target the first two explicitly by entirely typing it out (e.g. release).

What rules would we apply to our feature branch? Well, none… they are meant to be disposable.

If your branch naming convention is more specialized, you can do all sorts of fancy things with the fnmatch syntax - just read GitHub’s Docs on it.

Adding guardrails

Justice is blind ⚖ - enforce rules equally

Checking the “Include Administrators” box will force everyone on the team to play by the same rules. Sorry admins, no special privileges when it comes to the health of our branches.

Psst, admins, you can always temporarily disable these rules if you’re in a pinch. Let’s at least act like we are on a level playing field for now.

A second set of eyes 👀 - Required Reviews

In my opinion, this is the most potent protection rule. Checking the “Require pull request reviews before merging” box will ensure a second set of eyes is on your code. To get your code deployed, you will need a colleague to review and approve your work. So play nice!

This protection is potent because both sides, author and reviewer, benefit. The author has their work validated by a trusted colleague. The reviewer receives cross-training just by working through someone else’s code.

A second set of robot eyes 🤖- Required Status Checks

In a similar vein to the required reviews, the “Require status checks to pass before merging” box ensures all the automatic review processes are satisfied. We need to appease our robot friends. For our analytics build, this means having the “dbt Cloud” CI job complete smoothly.

If you want to learn more about getting the most of the dbt Cloud CI job, you can dig into it more here.

Keys to deploy 🔑 - Restrict who can push

If you want only a specific group of individuals to accept the pull requests, then this last branch protection rule is what you need. In my case, feature branch authors should merge their own PRs to the review branch after passing the code review. But the stakes for deploying from release to master are higher, so only a couple of us are allowed to take that final step to production.

Restricting who can accept PRs puts more responsibility on a few people. This additional pressure on a few individuals creates relief for the organization when audited for clear separation of duties. No author should push their own code to production.

Conservation Efforts Assessment

Adding protection to your branches helps avoid catastrophic consequences but decreases the flexibility of the team. It is a balancing act between friction-free collaboration and friction-free deployments.

Coming from a reformed coder cowboy, I now lean towards friction-free deployments. Uptime and accuracy are critical to maintaining the hard-won trust of colleagues in the organization.

Take action. Protect your branches.