This post explains how to protect branches on your Git server (implemented by JGit HTTP server). It needs to be done in two steps:
- Setup pre-receive-hook
- Add a new property in git-config
Pre-receive-hook
A org.eclipse.jgit.transport.PreReceiveHook is a hook invoked by ReceivePack before any updates are executed. According to JGit Javadoc, the hook is called with any commands that are deemed valid after parsing them from the client and applying the standard receive configuration options to them:
- receive.denyDenyDeletes
- receive.denyNonFastForwards
This means the hook will not receive a non-fast-forward update command if
denyNonFastForwards
is set to true in the configuration file.
As the hook is invoked prior to the commands being executed, the hook may choose
to block any command by setting its result status with
ReceiveCommand.setResult(ReceiveCommand.Result).
This is what we’re doing
here—we will set the result to “REJECTED” when any non-fast-forward updates is
detected.
Once the pre-receive-hook is created, you can include it into receive-pack-factory, as part of the receive-pack handling:
However, this might not fit your need, because:
- It cannot prevent non-fast-fastforward updates based on branch names.
- It does not differentiate one repository’s update-policy from another.
For the 1st point, it’s easy. You just need to add more logic into the
pre-receive-hook. For example, protecting only the master branch
(refs/heads/master
) can be done as follows:
For the 2nd point, let’s see the next section.
Git Config
If you need to have an individual protection policy on each repository hosted,
you can also define a git configuration property “receive.denyNonFastForwards”
in repo’s Git configuration (.git/config
). Therefore, pre-receive-hook
understand how to deny the non-fast-forward updates:
The equivalent Java code which writes this property into Git configuration file:
Once the configuration is correctly set, you can use the builtin method of
receive-pack ReceivePack#isAllowNonFastForwards
to determine if the repo
allows non-fast-forward updates: