EMZETT.
Login

Git hooks and pre-commit: Automatic checks before the commit

In short: Git hooks run scripts on certain events, such as before a commit; this lets formatting, linting, tests and secret scans be enforced automatically.

In more detail: Finding errors early saves time. Git hooks are scripts in the folder .git/hooks/ that Git starts on events: pre-commit, commit-msg, pre-push, post-merge and others. If a hook returns an error code, Git aborts the action.

In Depth

Example: own hook

#!/bin/sh
# .git/hooks/pre-commit  (make executable: chmod +x)
npm run lint --silent || {
  echo "Lint errors: commit aborted"; exit 1;
}

Problem: .git/hooks is not versioned and not shared with the team. Better: manage hooks with a tool that installs them from the repository.

Tools

  • pre-commit (Python-based, language-independent): configuration in .pre-commit-config.yaml, installation pre-commit install; hooks for Black, Ruff, Prettier, ESLint, shellcheck, gitleaks, trailing whitespace and much more.
  • Husky + lint-staged (JavaScript): checks only changed files.
  • Lefthook (fast, Go).
  • In the Git configuration: git config core.hooksPath .githooks if the folder lies in the repo.
# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.5.0
    hooks: [{id: ruff}, {id: ruff-format}]
  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.18.0
    hooks: [{id: gitleaks}]

What to have checked

  • Formatting and linting (keep fast so nobody bypasses the hooks).
  • Secrets (gitleaks) and large files.
  • Commit messages (commit-msg, Conventional Commits).
  • Quick tests before the push (pre-push).
  • No merge-conflict markers, no console.log/debugger. Slow checks (the full test suite) belong in CI.

Limits

Hooks are local and bypassable (git commit --no-verify), so no replacement for CI and server rules (branch protection, required checks, required reviews). They are a convenience that makes errors visible early. Keep them fast (under a few seconds), document the setup in the README and check again in CI.

See also: CI/CD pipeline, Conventional Commits, Managing secrets