Prevent commits in master branch
GitMergeFast ForwardGit Problem Overview
(For simplicity) I have a master
branch and a dev
in my Git repository. I want to ensure the master
branch is always working, so all work I do should be in the dev
branch.
However, when I merge my changes in with a --no-ff
merge, I tend to stay in the master
branch, and just continue working in it (because I forget to checkout my dev
branch).
Can I put up a rule for the master
branch, which states I can't do commits, and fast-forward merges, but only --no-ff
merges from another branch?
This must work for private hosted repositories (ergo, not GitHub or Bitbucket).
Git Solutions
Solution 1 - Git
Yes, it is possible. You must create a pre-commit hook which rejects commits to the master branch. Git doesn't call a pre-commit hook when you call the merge command, so this hook will be rejecting only regular commits.
-
Go to your repository.
-
Create a file, .git/hooks/pre-commit, with the following content:
#!/bin/sh branch="$(git rev-parse --abbrev-ref HEAD)" if [ "$branch" = "master" ]; then echo "You can't commit directly to master branch" exit 1 fi
-
Make it executable (not required on Windows):
chmod +x .git/hooks/pre-commit
To disable fast-forward merges, you must also add the following option to your .git/config file:
[branch "master"]
mergeoptions = --no-ff
If you want also protect the master branch on your remote, check this answer: How to restrict access to master branch in Git
Solution 2 - Git
You can use the pre-commit utility to do this. It has a built-in no-commit-to-branch
hook that can be used to prevent commits to one or more branches.
Setup
The basic setup process is:
- Install using pip or Homebrew (instructions at https://pre-commit.com/#install)
- Create a
.pre-commit-config.yaml
file in the root of your project (see below for a first draft) - Install the hooks into your Git configuration by running
pre-commit install
.
Basic configuration for protecting branches
Here is a basic configuration that includes just the no-commit-to-branch
hook:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.3.0
hooks:
- id: no-commit-to-branch
args: ['--branch', 'master']
If you want to protect multiple branches, you can use include multiple --branch
arguments in the argument list:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.3.0
hooks:
- id: no-commit-to-branch
args: ['--branch', 'master', '--branch', 'staging']
Isn't this all overkill?
Pre-commit has many other built-in hooks, and a large collection of community-built hooks that will transform the way you clean up and validate your commits. The reason I mention this is because, while this tool may be overkill for just preventing commits to a protected branch, it has many other features that make it a compelling and simple addition to any Git project.
Solution 3 - Git
It may make sense to install it globally via
git config --global core.hooksPath ~/githooks
and moving that pre-commit
file into that directory