Prevent commits to the local git master branch

I’ve been a fan of Yelps pre-commit git hook manager ever since I started using it to Prevent AWS credential leaks. After a recent near miss involving a push to master I decided to take another look and see if it could provide a safety net that would only allow commits on non-master branches. It turns out it can, and it’s actually quite simple to enable if you follow the instructions below.

Firstly we’ll install pre-commit globally.

pip install pre-commit

Before we enable the plugin we’ll make a commit to an unprotected local master branch to ensure everything’s working the way we think it is.

# confirm we're on master
$ git branch
* master

# create a local change we can work with
$ echo "Text" >> text

$ git add text

# successfully commit the change
$ git commit -v -m "Add text"
[master e1b84e5] Add text
 1 file changed, 1 insertion(+)
 create mode 100644 text

Now we’ve confirmed we can commit to master normally we’ll add the pre-commit config to prevent it.

$ cat .pre-commit-config.yaml
- repo:
  sha: v0.9.5
  -  id: no-commit-to-branch

and then we activate the config.

$ pre-commit install
pre-commit installed at ~/protected-branch-test/.git/hooks/pre-commit

If anything fails then you’ll probably need to read through ~/.pre-commit/pre- commit.log to find the issue. Now we’ve installed the pre-commit pip, added its config, and then enabled it we should be protected. No more accidental committing to the master branch for us! But let’s verify.

# make a change to the checkout
echo "More text" >> text

git commit -m "Added more text"
... snip ...
Don't commit to branch.............Failed
... snip ...

# and the change is not committed.

By default this plugin protects the master branch. If you have other branches you want to deny commits on you can add the args key to the config as shown in this snippet.

  -  id: no-commit-to-branch
     - --branch=release

If you need to commit to master while this plugin is enabled you can use the --no-verify argument to git commit to disable all pre-commit hooks.

It’s worth noting you can also prevent inadvertent pushes to master at the remote end by enabling branch protection on a number of the popular git providers, both GitHub and BitBucket support this. This approach has the advantage of not needing client side configuration but does require that all your providers support it, and that you actually enable it on each of them and their repositories. While you can of course do that by hand there are also a few tools that will manage this for you, but that’s a something for a different post.