Skip to content
TutorialDevOps

Laravel 13 Git Hooks with Husky: Pint on Every Commit

D

Dinesh Wijethunga

September 5, 2026 3 min readBeginner
ShareX / TwitterLinkedIn
Laravel 13 Git Hooks with Husky: Pint on Every Commit

In this tutorial, I will show you step by step how to set up git hooks in Laravel 12 with Husky, with a complete example from a production Laravel + React (Inertia) repo.

The goal: nobody can commit unformatted PHP, and nobody can push broken JavaScript — while keeping every hook fast enough that no one is ever tempted to bypass it.

Step 1 — Install Husky

npm install --save-dev husky
npx husky init

This creates a .husky/ directory and adds a prepare script to package.json, so every developer gets the hooks automatically on npm install:

"scripts": {
    "prepare": "husky"
}

Step 2 — The pre-commit hook: Pint on staged files only

The naive version runs Pint on the whole project. Don't — it reformats files your teammate is mid-way through, and it's slow. The correct version formats only the PHP files in this commit, then re-stages them so the fixes ride along:

# .husky/pre-commit
STAGED_PHP=$(git diff --cached --name-only --diff-filter=ACM | grep '\.php$' || true)

if [ -n "$STAGED_PHP" ]; then
    echo "husky: pint on staged PHP files…"
    ./vendor/bin/pint $STAGED_PHP
    git add $STAGED_PHP
fi

Three details that matter:

  • --diff-filter=ACM — added, copied, modified. Deleted files are excluded, otherwise Pint errors on paths that no longer exist.
  • || true — grep exits non-zero when nothing matches, which would abort every PHP-free commit.
  • git add $STAGED_PHP — Pint's fixes are re-staged, so what lands in the commit is the formatted version. No follow-up "apply pint" commits, ever.

Step 3 — The pre-push hook: the fast test wall

# .husky/pre-push
echo "husky: JS tests…"
npm run test:js

echo "husky: pint check…"
./vendor/bin/pint --test

# Optional: uncomment to also run a critical PHP test group (keep it FAST)
# composer test:critical

On our repo the JS suite runs in about 3 seconds and pint --test (check-only mode, no writes) in about 2. A failed push looks like this and never leaves the machine:

husky: JS tests…
 FAIL  resources/js/__tests__/invoice-totals.test.ts
error: failed to push some refs

Why the full PHP suite is deliberately NOT in the hooks

Our full Laravel suite is 340+ tests against a real MySQL server — several minutes. Here is the uncomfortable truth from every team I've taught this to: any hook slower than about ten seconds gets bypassed. Developers discover git push --no-verify on day two, and now your "safety net" is theatre.

So the contract is: hooks catch the cheap mistakes instantly, and the full suite runs in Jenkins on every push — where it blocks the deploy, not the developer. That pipeline is exactly what the rest of this series builds.

Verify it works

Deliberately mangle a file and try to commit:

echo 'class   Foo{public function bar( ){return 1 ;}}' >> app/Models/Scratch.php
git add app/Models/Scratch.php && git commit -m "test hook"
# → pint reformats it, re-stages, commit lands clean
git show --stat HEAD

Next in the series: post #3 installs Jenkins on Ubuntu 24.04 — including the two apt traps that produce the infamous "Package 'jenkins' has no installation candidate" error in 2026.

Frequently Asked Questions

Why not run PHPUnit in the pre-push hook?
A full Laravel suite against MySQL takes minutes. Hooks slower than ~10 seconds get bypassed with --no-verify, which defeats the purpose. Run fast checks locally and the full suite in CI.
Does Husky work for PHP projects?
Yes. Husky only needs npm to install; the hook scripts are plain shell and can run any command — Pint, PHPStan, Pest, anything.
D
Dinesh Wijethunga

Senior Full Stack Developer · Building SaaS products & teaching Laravel/React · 10+ years experience · Founder of Orion360 · Based in Dubai, UAE.

Was this post helpful?

Add a comment

Comments

Guest comments are held for moderation.

You might also like

Deploy Laravel to a VPS with Laravel Forge: Complete Walkthrough
TutorialIntermediateDevOps

Deploy Laravel to a VPS with Laravel Forge: Complete Walkthrough

Laravel Forge isn't a host — it turns any VPS into a managed Laravel server. Full walkthrough: provisioning, GitHub push-to-deploy, the deploy script, one-click SSL, queue workers, the scheduler, and an honest look at zero-downtime options.

D
Dinesh Wijethunga
5 months ago
6m