Server-Side Git Hooks Worth Running on Your Own Server

Server-Side Git Hooks Worth Running on Your Own Server

21 October 2026 · By Laravel Git · 2 min read

Local hooks (the kind in git hooks for Laravel projects) run on the developer’s machine, which means they run only when the developer kept them installed. Server-side hooks run on every push, for everyone, no exceptions. When you self-host, they are one of the best reasons to - and one of the easiest ways to annoy your team if you overreach.

Three checks that earn their place#

1. Block the secrets. A pre-receive hook scanning pushed commits for private keys, .env contents and common token shapes turns a secret got committed from an incident into a rejected push. Gitleaks or a few good regexes; the point is that the secret never lands in the repo’s history at all, which is when cleanup is free.

2. Protect the default branch. Even with branch protection rules configured in the UI, a pre-receive or update hook rejecting direct pushes to main is the belt to the platform’s suspenders - it still fires if someone widens a permission by mistake.

3. Refuse giant blobs. A 200MB binary committed once lives in every clone forever. Rejecting pushes with files over a sane limit (100MB is GitHub’s line; yours can be lower) pushes large assets to Git LFS before they become permanent.

The restraint that keeps them tolerable#

A rejected push interrupts someone mid-flow, so every hook owes them three things:

  • A fast answer. A hook that scans ten thousand commits on every push will be bypassed, not loved. Check the pushed range, not all of history.
  • A message that says how to fix it. “Push rejected: possible secret in src/config/legacy.php (line 41). Remove it, rewrite the commit, see .” A bare “rejected” teaches people to fear the server; a clear one teaches them the rule.
  • A real escape hatch. False positives happen - a test fixture that looks like a key, a legitimate big file. Someone on the team should be able to bypass with a reason, and that bypass should be logged, not forbidden.

Start with the secret scanner; it has the best ratio of one-time setup to incidents prevented. Add rules the way you add tests: when the failure actually happens, not in anticipation of every imaginable one.

Share this post

Our network