← all lessons
Software Engineering · lesson 15 of 18

Git Hooks & Automation

Automate Quality

Why it matters

Automation catches mistakes before they become problems. Git hooks enforce quality standards at commit time. CI/CD extends this to the entire pipeline.

Key concepts

The idea

The Quality Gate

Hooks are scripts that run automatically at key points:

Pre-commit: Before commit is created

Pre-push: Before push to remote

CI/CD: After push to remote

Walkthrough

Git Hook Locations

.git/hooks/
├── pre-commit         # Before commit
├── prepare-commit-msg # Edit default message
├── commit-msg         # Validate commit message
├── pre-push           # Before push
├── pre-rebase         # Before rebase
└── post-merge         # After merge

Simple Pre-Commit Hook

#!/bin/bash
# .git/hooks/pre-commit

# Run linter
npm run lint
if [ $? -ne 0 ]; then
    echo "Linting failed. Fix errors before committing."
    exit 1
fi

# Check for console.log
if git diff --cached | grep -q "console.log"; then
    echo "Warning: console.log found in staged changes"
    read -p "Continue anyway? (y/n) " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        exit 1
    fi
fi

exit 0

Using Husky (Node.js)

# Install
npm install husky --save-dev
npx husky init

# Add pre-commit hook
echo "npm run lint" > .husky/pre-commit

# Add commit-msg hook (with commitlint)
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg

Using pre-commit (Python)

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.4.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-added-large-files

  - repo: https://github.com/psf/black
    rev: 23.3.0
    hooks:
      - id: black

  - repo: https://github.com/gitleaks/gitleaks
    rev: v8.16.1
    hooks:
      - id: gitleaks
# Install
pip install pre-commit
pre-commit install
pre-commit run --all-files

GitHub Actions CI

Server-side automation — GitHub Actions, or classic CI servers like Jenkins — runs your checks on every push.
# .github/workflows/ci.yml
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Test
        run: npm test

      - name: Build
        run: npm run build

Key takeaways

Dos & don’ts

✅ DO

❌ DON’T

Going deeper

Branch Protection Rules: GitHub can require:

Secret Scanning: GitHub automatically scans for leaked secrets. Add gitleaks to pre-commit for local protection.

Common mistakes

Hooks not shared: .git/hooks/ isn’t tracked. Use Husky, pre-commit, or commit scripts to share.

Skipping hooks too often: If everyone uses --no-verify, hooks are useless. If hooks are too slow/annoying, fix them rather than bypassing.