When NOT to use Pre-receive hooks in GitHub Enterprise

The story so far

We’ve explored pre-receive hooks as implemented in GitHub Enterprise, and specifically how and when to implement them. That said, pre-receive hooks are not a panacea, and there are other tools that are better suited when you want to add constraints when pushing your code.


Security scanning

One of the first use cases that comes to mind is security scanning. Catching private keys, security credentials, and other access codes before they are even made public and refusing pushes sounds like a perfect use for pre-receive hooks! However the constraints inherent to pre-receive hooks make them a poor choice for this:

  • Server-side Git data does not have a concept of working copy, which means that anything that needs to access the contents of a modified file has to checkout that file first.
  • Pre-receive hooks run after data has been recorded in the Git history, but before it has been copied back to the origin. This means that the commit history must be rewritten to remove the whole file or revision, which comes with its own challenges. In comparison, commits metadata can be modified with git commit --amend, for instance.
  • Larger pushes, which can contain either a large number of files, a large number of commits, or large files (or both!) add to the pre-receive hook runtime and will hit the preset timeout. Bypassing said timeout is not possible, and would severely impact the stability and performance of your instance otherwise.

Two options are available:

Use pre-commit hooks instead. This ensures critical data never leaves the workstation in the first place. Changes cannot be saved until the issues are addressed, and execution time is not constrained by timeouts.

Use webhooks and an external service to scan for known critical data. This has several key benefits. When critical data is detected, the external service is configured to automatically roll the credentials and notify the relevant stakeholders.

  • You can make the distinction between test data and actual live data by comparing them against your infrastructure, instead of rejecting based on a pattern.
  • Having a system that can automatically invalidate and renew keys, tokens, and other critical data prepares you to handle security incidents that happen outside of GitHub Enterprise. For instance, dealing with compromised workstations or storage devices.
  • You can run as many checks on as many patterns as you want, without exceeding time limits.


Style checks

Let’s say you want commits to match a specific coding style, or confirm the work done is tracked against the correct issue in your issue tracker. Again, using pre-receive hooks delivers immediate feedback…or does it?

Similarly to security scanning, pre-receive hooks do not handle large amounts of data very well. They also make it difficult to get an accurate report of the style violations. Additionally, relying on external systems to block or allow pushes can have strict consequences when a third-party server is unavailable or experiencing degraded performance.

A better alternative would be to configure protected branches and required status checks:

  • Configure a webhook to trigger on every push that will forward the push payload to a build server of your choice.
  • Then configure your required checks, and use the Statuses API endpoint to set the status, being one of error, failure, pending, or success.
  • Finally, configure your protected branches to prevent changes being committed directly to your default branch, and enforce required status checks using the status you’ve implemented.

There are several advantages to this process:

  • Work is not blocked, but changes cannot be merged until issues are fixed. Further commits to fix issues can be pushed, instead of having to rewrite history.
  • You’re not depending on a third-party system being online and responding quickly 100% of the time.
  • A select group of users can fast track urgent changes by dismissing required checks, for instance to implement an emergency security fix.
  • You can identify build errors ahead of time, and once your changes are confirmed to be working, you can over and fix the syntax as well.



While pre-receive hooks are a powerful Git feature available to GitHub Enterprise administrators, they act as a complement to other features that assist your workflow rather than impede it. These are just a couple scenarios where pre-receive hooks are not the best solution. Have you run into other situations that seemed like they would be perfect for using pre-receive hooks but then caused issues? Let us know in the comments below!


Thanks @frconil for this amazing article.  I am just trying to figure out how i can use pre-receive environment to build a custom python package that will check some commits with pre-receive.

It seems impossible to do on GitHub Enterprise (I built some custom env but it seems i still need to pass a bash script in GHE). I am missing something ? 

Some other questions about your article:

The big advantage of the pre-receive compared to webhook is to avoid than credentials will be spread everywhere (Automatic rolling can be impossible or too dangerous) . You speak about the credentials still being there but in git objects but it seems they will be deleted just after the push is rejected (https://git-scm.com/docs/git-receive-pack#_quarantine_environment) ?

What is the timeout issue for push mentionned here ?

Cheers from France :slight_smile:

Bonjour! (ou Bonsoir?)

There is two parts to a pre-receive hook: The script itself which will process every commit, and in some cases, a custom environment that contains the libraries and utilities necessary for the hook to run (like the python package, for instance). You can learn more about pre-receive hooks environments in our GitHub Enterprise documentation.

The credentials are still present in the git history on the client side, and the commits in question will have to be removed from the git history. Let’s not forget that credential security is not about “if” but about “when”. Attackers need to be lucky only once while defenders need to be lucky every time. Having a detection and remediation framework can be used for more than only the developers’ work :wink:

If you really want to credentials to be leaked, then pre-commits are really the way to go. They can be rolled out quickly with your configuration management tool of choice.

We do have a hard timeout which cannot be mofidied to ensure that pages are displayed without errors, and for internal workers to not be tied by a single push. For large pushes (raw SQL data, or minified JS for instance, but it can be anything), the execution time of a non-optimised script can be in the order of minutes.

Don’t hesitate to reach out at https://support.enterprise.github.com/hc/en-us if you have further questions! Our team would be happy to assist.