Git Hooks - Automate on Events

Git Hooks

Hooks are ordinary scripts that Git runs automatically at specific points in its own workflow - for example, right before a commit is finalized, or right before a push leaves your machine. They let you enforce standards locally, catching problems before bad code ever enters history at all, rather than relying only on CI to catch it after the fact.

HookFiresCommon use
pre-commitRight before a commit object is createdLint, auto-format, run fast tests, block obvious secrets
commit-msgRight after you've written the commit messageEnforce a message format (e.g. Conventional Commits like fix: …)
pre-pushRight before a push leaves your machineRun the full test suite one last time

Hooks live as executable scripts inside .git/hooks/ - Git ships that folder with harmless .sample files already, and you activate one just by creating a real, executable file with the exact hook name (no extension):

$ cat > .git/hooks/pre-commit <<'EOF'
#!/bin/bash
if git diff --cached | grep -q 'API_KEY='; then
  echo 'Blocked: do not commit secrets!'; exit 1
fi
EOF
$ chmod +x .git/hooks/pre-commit

That exit 1 is the whole mechanism: any hook that exits with a non-zero status stops the action it guards. A pre-commit hook exiting non-zero aborts the commit entirely, before it's ever created.

Warning: .git/hooks/ lives inside the .git folder, which is never committed or shared with the rest of the team - each teammate's clone starts with none of your hooks active. To actually share hooks across a team, use a tool like Husky (JavaScript projects) or the pre-commit framework (Python and language-agnostic), or point Git at a tracked folder with git config core.hooksPath <dir> so the hooks themselves live in version control.
Tip: A shared pre-commit hook that blocks obvious secrets and runs a linter catches problems on every contributor's machine, before code ever reaches CI or a human reviewer - cheaper and faster feedback than waiting for a PR check to fail minutes later.