Branch protection is part of a powerful set of configuration options that give repository administrators the ability to enforce security policies by preventing accidental branch deletions, enforcing code reviews, and requiring successful automated checks before pull requests can be merged.
These options offer an effective way to elevate code quality without creating artificial obstructions to effective collaboration. Finding the right combination of settings to achieve the desired effect is very important.
This article will explore best practices to help you maintain a healthy codebase without impairing collaboration. You will learn when and how to use required status checks, branch restrictions, required reviews and more.
Branch protection for organizations
Collaborators with write access to a repository have complete write permissions on all its files and history. While this is good for opening up the doors to collaboration it's not always desirable: for instance, a collaborator may accidentally delete an important branch or overwrite its commit history by force pushing incompatible changes. Another common scenario is that of a collaborator introducing bugs by adding work that hasn't been tested.
GitHub offers a number of tools to achieve frictionless collaboration and help you keep your repositories in good shape without littering your development workflow with unnecessary obstructions.
Protect this branch
Protected branches are a safety net designed to protect your code from catastrophic actions rather than particular people.
You can select any branch in any repository and by enabling this setting you will ensure the following safeguards:
the branch cannot be deleted, either accidentally or intentionally
the branch commit history cannot be overwritten with an alternate set of changes (force push)
That applies to command line users as well as to the GitHub web UI.
⚠️ Please note: collaborators with write permissions pushing commits to the top of a protected branch, either directly or by merging pull requests without merge conflicts will remain unaffected by this setting. That's because merging a pull request is in fact equivalent to pushing its commits to the target branch.
✅ Do: enable branch protection to effectively prevent force pushing e.g. to prevent rewriting the commit history. Tip:check the box for Include administrators at the bottom of the page to also apply this setting to organization and repository administrators.
✅ Do: enable branch protection on the master branch or any branch meant for ongoing collaboration. Feel free to skip for "work in progress" style branches which are meant to be eventually merged and deleted.
✅ Do: temporarily disable branch protection if it's necessary to force push commits to the branch. Sometimes this may be unavoidable: in those circumstances we advise all necessary precautions should be used and collaborators notified.
⛔️ Don't: expect branch protection to prevent pushing commits which don't alter the commit history. If you want to disable pushing directly to the branch, use the setting Require pull request reviews before merging instead.
It's possible to restrict the teams or individuals who can push to a branch at all by enabling the option Restrict who can push to this branch and specifying their names on the list. By default, all collaborators who have been granted write permissions to the repository are able to push to the protected branch. By explicitly specifying permitted collaborators, you will narrow down the list of existing collaborators who can push to the branch.
When and how to use branch restrictions
It's important to understand the implications of using this option especially in conjunction with the others. Let's look at a common scenario:
I want to prevent someone from pushing their local changes directly to the remote branch; at the same time I don't want to prevent their pull requests from being merged.
Restrict who can push to this branch is intended to exclude users or teams from pushing to important branches using any method, including merging their own pull requests onto the target branch. As we already saw in this article, merging a pull request is effectively the same as pushing commits to a branch. By enabling this setting you can prevent a user from pushing commits to a branch while still allowing them to open pull requests.
This will prevent them from being able to merge their own pull requests and require that only those in the restricted list can proceed with the merge operation.
✅ Do: create a "Maintainers" team of repository maintainers if you want to explicitly restrict push permissions to a specific set of collaborators. This allows you to simply add the team to the list instead of having to type in each maintainer individually. It's also one less thing to maintain when you are ready to promote collaborators to the maintainers team!
✅ Do: use this option as a way to bypass pull request based worfklows for those bots or other apps that need to be granted permissions to push directly to the branch.
⛔️ Don't: enable branch restrictions if your goal is to ensure changes need to be approved before collaborators can merge their own work. Use Require pull request reviews before merging instead to spare maintainers from having to merge each individual pull requests.
Require status checks to pass before merging
If you test your code with a continuous integration system that sends build statues back to GitHub (such as CircleCI, Travis or Jenkins) you can avoid broken code by requiring one ore more status checks to pass on a branch before allowing pull requests to be merged.
Each individual CI system connected to your repository will be listed here and you can individually specify required ones.
Let's take a look at the following:
I want to prevent pull requests being merged unless all the tests are all passing and nobody should be able to push directly to master .
The above can be achieved by enabling branch protection on master, turning on Require status checks to pass before merging and by specifying the tool(s) executing the test suite as required. To avoid direct pushes, simply enable Require pull request reviews before merging (more below).
Another very common request is:
I want my CI checks to run again if something has changed on master since a pull request has been opened.
By also enabling Require branches to be up to date before merging you can make sure that checks are ran against the latest state of the target branch. If the code on the target branch has changed since a pull request has been opened, a message will appear to indicate that those changes need to be merged upstream into the pull request branch before merging. Once the changes are integrated a new build will be triggered and the status checks will update to reflect the latest state.
✅ Do: use the checkbox to Include administrators to ensure this is applied to all collaborators.
✅ Do: use required checks in conjunction with Require pull request reviews before merging to achieve an effective collaboration workflow based on pull requests.
Require pull request reviews before merging
Code reviews are a critical part of any development workflow. You can require at least one review and approval by checking the Require pull request reviews before merging checkbox. This option alone is very useful and when used in conjunction with required status checks it provides teams certain "collaboration guardrails" to help with writing better code while maintaining high levels of productivity.
In fact when you enable this setting you will ensure that:
no pull request can be merged without at least one approved review
prevent collaborators from pushing directly to the branch (and merging their own pull requests)
Pull request authors must either respond to requested changes, or dismiss a review, if they are not restricted from doing so by the Restrict who can dismiss pull request reviews option.
✅ Do: use automated code review tools to enforce objective code quality aspects (such as coding style guidelines) to introduce a point of objectiveness in the process of code review and help keep discussions between developers focused on more important things.
✅ Do: enable the extra flag Dismiss stale pull request approvals when new commits are pushed to make sure that reviewers are notified when new changes are pushed to a pull request they have already approved.
Require review from Code Owners
Another important tool that repository administrators have at their disposal is Require review from Code Owners. Let's review the following situation:
I want to ensure that all changes touching CSS files (e.g. *.css ) are reviewed by our design team; at least one administrator needs to approve the pull request before merging.
Repository administrators can define exactly which people and teams need to review projects using the CODEOWNERS file. This new feature automatically assigns reviewers based on Code Owners when a pull request changes any owned files, using the same syntax as the .gitignore file.
✅ Do: use the CODEOWNERS file to ensure that changes to specific areas of the codebase are always reviewed by those with the most expertise.
In this article we have seen how branch protection can increase team productivity without hindering collaboration while also giving great levels of flexibility to repository and organization administrators looking to enforce the right collaboration policies to secure their software development workflows.
If you want to learn more we recommend the following list of links from the documentation and support pages:
Best practices for pull requests
Repository permission levels for an organization
About branch restrictions
About protected branches
About required status checks
About status checks
... View more