Changes: - Format only staged PHP files (not all dirty files) - Auto-stage only the files that were already staged - Prevents accidentally staging unstaged changes - Safer for partial staging workflows - Maintains full automation for normal commits This aligns with industry best practices from lint-staged and prevents security risks from staging unintended files. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Git Hooks for Cannabrands CRM
Best Practice: Graduated Enforcement
Defense in Depth Strategy:
- Pre-commit hook (ENFORCED) - Auto-format code (~1 second)
- Pre-push hook (OPTIONAL) - Run tests before push (~30-60 seconds)
- CI pipeline (REQUIRED) - Final verification, blocks deployment
Installation
One-time setup (after cloning):
# Configure Git to use .githooks directory
git config core.hooksPath .githooks
# Make hooks executable
chmod +x .githooks/*
Available Hooks
pre-commit - Laravel Pint Auto-formatter ✅ ENFORCED
What it does:
- Runs Laravel Pint on staged PHP files only (not unstaged files)
- Auto-formats code to match team standards
- Automatically re-stages the formatted files
- Fast feedback (runs in seconds)
- Safe: Won't format or stage files you haven't explicitly added
When it runs:
- Every time you run
git commit - Before your commit is created
Bypass if needed:
# Skip hooks (not recommended, CI will still catch it)
git commit --no-verify -m "message"
pre-push - Test Runner ⚠️ OPTIONAL (Recommended)
What it does:
- Runs your test suite before pushing
- Catches failing tests before CI runs
- Saves time by finding issues locally
When it runs:
- Every time you run
git push - Before code is sent to remote
Bypass when needed:
# Skip when pushing WIP or non-code changes
git push --no-verify
Why optional?
- Takes 30-60 seconds (vs formatting's <1 second)
- Sometimes you want to push WIP to share with team
- CI will catch it anyway as final gate
Enforcement Levels Explained
| Hook | Speed | Enforcement | Can Bypass? | Purpose |
|---|---|---|---|---|
| Pre-commit | ~1s | ✅ Strict | Yes (but don't) | Code formatting |
| Pre-push | ~30s | ⚠️ Suggested | Yes (sometimes needed) | Run tests |
| CI Pipeline | ~5min | 🚫 Required | No | Final gate |
Example Workflows:
Scenario 1: Normal development
1. Make changes → git commit
→ Pre-commit runs Pint → Code formatted ✅
→ Commit created ✅
2. git push
→ Pre-push runs tests → All pass ✅
→ Code pushed to remote ✅
3. CI runs
→ Tests + Build → Everything passes ✅
→ Ready to deploy ✅
Scenario 2: Pushing WIP (work in progress)
1. Make changes → git commit
→ Pre-commit runs Pint → Code formatted ✅
2. git push --no-verify (skip pre-push tests)
→ Push WIP to remote ✅
3. CI runs
→ Tests fail (expected for WIP) ❌
→ Fix later before merge ✅
Scenario 3: Developer bypasses everything
1. git commit --no-verify (skip formatting)
→ Unformatted code committed ❌
2. git push --no-verify (skip tests)
→ Pushed to remote ❌
3. CI runs
→ Code style fails → Build fails 🚫
→ Can't deploy → Must fix ✅
Philosophy: Small Team Balance
"Make the right thing easy, and the wrong thing possible (but audited)."
For our 5-person team:
- Hooks make it easy to follow standards (automatic formatting)
--no-verifymakes it possible to bypass (for WIP/emergencies)- CI makes bypasses audited (they'll fail the build)
Why this works for small teams:
- ✅ Fast checks are automatic (no thinking)
- ✅ Slow checks are optional (developer discretion)
- ✅ Final gate blocks broken code (can't deploy)
- ✅ High trust, low friction
As team grows (10-20 developers):
- Consider making tests mandatory (remove
--no-verifyoption) - Add code review requirements
- Tighten enforcement where needed
Current enforcement is "Goldilocks" - not too strict (frustrating), not too lenient (risky), just right for 5 developers who know each other.
Troubleshooting
Hook not running?
# Check if hooks path is configured
git config core.hooksPath
# Should show: .githooks
# If not, run: git config core.hooksPath .githooks
Hook permission denied?
chmod +x .githooks/pre-commit
Want to test hook without committing?
./.githooks/pre-commit