Github does not make it obvious how to protect your primary branch from direct pushes.
(Nowadays the primary branch is usually named
main, but you wil still see the name
master in the wild. For this
post I’m going to reference
The problem, with a typical setup, Administrators are allowed to push to
main. Force pushing is protected by
default, but not regular old pushing.
The other problem is we’re all human, especially us Administrators.
I’ve more than once accidentally pushed to
main thinking I was on a feature branch. But alas I wasn’t.
So I argue preventing all users, even Admins, pushing to
main is the ideal. I guess Github doesn’t see it my way.
Option 1: Update the Repo Settings⌗
Navigate to your project’s settings and change the branch protection rules.
Check this box:
Now when you push to
main you’ll see this error:
! [remote rejected] main -> main (protected branch hook declined)
But there’s some gotchas.⌗
First, Github repos on the free plan may not have this option. Gotta pay to protect yourself from yourself, I guess.
Second, you will no longer see the admin override checkbox on PRs.
I like that checkbox. I don’t use it often. You shouldn’t use it often. But sometimes, you have to get an emergency PR out the door.
There are less-ideal workarounds. An admin can temporarily disable the push protection. But then you have the onerous task of remembering to turn it back on when you’re done.
Option 2: Hack your Git Config⌗
git config branch.main.pushRemote push_to_main_not_allowed
This is a hack that sets the remote to a bogus repository.
The hack works well, but my only issue is you get a confusing error message when it fails:
fatal: 'push_to_main_not_allowed' does not appear to be a git repository fatal: Could not read from remote repository.
git config --edit
And delete the
You could set this in your global git config. And I almost did. But, I have several side projects (like this blog) where I often push directly to
Option 3: Git Hooks⌗
Create this file as
#!/bin/sh branch="$(git rev-parse --abbrev-ref HEAD)" if [ "$branch" = "main" ]; then echo "main branch commit is blocked" exit 1 fi
This stops you from making any commits to