Best practices for protected branches

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.

:warning:  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.

:white_check_mark:  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.

:white_check_mark:  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.

:white_check_mark:  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.

:no_entry:  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.

Branch restrictions

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.

:white_check_mark:  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!

:white_check_mark:  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.

:no_entry:  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.

:white_check_mark:  Do:  use the checkbox to  Include administrators  to ensure this is applied to all collaborators.

:white_check_mark:  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.

:white_check_mark:  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.

:white_check_mark:  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.

:white_check_mark:  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:


@pierluigi, I’m interested in this particular idea: " 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" (w.r.t. to the " Restrict who can push to this branch" setting). However, I don’t see a way of making this work – i.e. I don’t know how to configure branch protection to allow a subset of users to push directly to the branch while requiring everyone else to submit a PR. Could you elaborate on how to do this?


1 Like

Hi @cobrabr thanks for the comment. Please note that: The ability to restrict branches is a type of branch protection that’s available for public and private repositories owned by organizations in GitHub Team, GitHub Enterprise Cloud, and GitHub Enterprise Server. From: this helps!

Yeah, I know where to do it, but I don’t know how to use it to bypass the PR workflow, as you suggested. If I turn it on in the same rule in which I enable  Require pull request reviews before merging , then only the users I specify can actually merge PRs as well, which is not what I need. What I need is to set up a bypass for a few users – everyone else should need to submit a PR, but those users should be able to push/merge directly. That’s what I’m having trouble setting up.


@pierluigi I have a similar question to @cobrabr . I really want to enable “Require status checks to pass before merging” but I only want it to affect PRs. I want all users to still be able to push directly to the branch if they want. Is there some way to set “Require status checks to pass before merging” only for PRs without locking our direct pushes to the branch?


Hi @pierluigi

I have the same question as @cobrabr, I need to give permission to a specific account to be able to push to the master branch without having to do a PR since it’s all executed during a GH action. But as of now it looks like there’s no way to do that because even if I add the user in the “Restrict who can push to matching branches” whenever he pushes GitHub raise an error telling me that he has to do a PR and that this PR has to be approved by one person.

Can you explain us how we can use this option?

Thank you!