bashintermediate

Git Hooks Pre-Commit Example

Git pre-commit and commit-msg hooks to enforce linting, tests, and commit message conventions.

bash
#!/usr/bin/env bash
# .git/hooks/pre-commit
# Make executable: chmod +x .git/hooks/pre-commit
set -euo pipefail

echo "Running pre-commit checks..."

# Get staged files
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM)

# Run linter on staged JS/TS files
TS_FILES=$(echo "$STAGED_FILES" | grep -E '\.(ts|tsx|js|jsx)$' || true)
if [[ -n "$TS_FILES" ]]; then
  echo "Linting TypeScript files..."
  echo "$TS_FILES" | xargs npx eslint --fix
  echo "$TS_FILES" | xargs git add
fi

# Check for debug statements
if echo "$STAGED_FILES" | xargs grep -l 'console.log\|debugger' 2>/dev/null; then
  echo "Error: Remove debug statements before committing" >&2
  exit 1
fi

# Run type checking
npx tsc --noEmit

echo "Pre-commit checks passed."

# ---
# .git/hooks/commit-msg
#!/usr/bin/env bash
# Enforce conventional commits: type(scope): description
COMMIT_MSG=$(cat "$1")
PATTERN='^(feat|fix|docs|style|refactor|test|chore|perf|ci|build)(\(.+\))?: .{1,72}$'

if ! echo "$COMMIT_MSG" | grep -qE "$PATTERN"; then
  echo "Error: Commit message must follow conventional commits format" >&2
  echo "Example: feat(auth): add login endpoint" >&2
  exit 1
fi

Use Cases

  • Enforcing code quality before commits
  • Standardizing commit message format
  • Running automated checks in development workflow

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.