We're using nagios to monitor our infrastructure. We don't have the nagios configs under version control at the moment, and there are two of us that manage nagios configuration. As such, I'm working to get our nagios config into a central git repo, using some hooks to do syntax checking and then if the configs look good, make them "active". I'm using this guy's post as a starting point.

Push is intercepted by the pre-receive hook, which takes the files, moves them to a temporary directory on the server, and runs them through the nagios syntax checker.

If the syntax checker passes, accept the push, then use the post-commit hook to git pull the new code into the live nagios configuration directory and then restart nagios.

If the syntax checker fails, reject the push, showing the nagios syntax error to the user.

I'm running into an odd behavior, though, when I reject a git push due to syntax errors in the nagios config. What I expect to happen is that if I reject the hook, the attempted push should leave the repository just how it was, untouched. That doesn't appear to be the case, though. Below are the details of what I'm seeing:

Problem

I edit the nagios config locally, intentionally including a syntax error, add, then commit locally:

The git checkout command in your hook is creating/updating the HEAD ref in your repository.

If your repository is a bare repository, it can live without a HEAD ref (new clones will default to checking out its master branch, if it has one); just delete the HEAD ref before exiting (maybe in a trap so that you do not have to arrange to do it before each exit individually). Anywhere “early” in your script:

If your repository is not bare, or you want to maintain a HEAD ref (so that clones will, by default, check out some other branch), then you will have to save the HEAD ref and restore it before exiting.

First, in the server’s repository, reset the HEAD ref to point to the branch that you want to be checked out by default in new clones:

By the way, pre-receive hooks should make sure that they fully read stdin and process all the lines they are fed. Exiting before consuming all the input can sometimes trigger a SIGPIPE in the git-receive-pack process; this probably does not come up in your case if you only push one ref at a time (since you read at least one line), but it is something to keep in mind. Probably it is easier to do this hook as an update hook where you only need to be concerned with one ref at a time and can reject each ref’s push individually (maybe you only care about keeping the tip of master “clean”; while you check and report on the tips of other branches, but never reject them so that they can be used for collaboration on incomplete work).