Skip to content

Git Hooks ​

GitLint integrates seamlessly with Git hooks to automatically validate commit messages before they're created. This guide covers hook setup and usage.

What Are Git Hooks ​

Git hooks are scripts that run automatically at certain points in the Git workflow. GitLint uses the commit-msg hook to validate messages before commits are finalized.

Installing Hooks ​

Automatic Installation ​

The easiest way to set up hooks:

bash
# Install commit-msg hook
gitlint hooks --install

# Force overwrite existing hooks
gitlint hooks --install --force

Manual Installation ​

Create .git/hooks/commit-msg:

bash
# !/bin/sh
gitlint "$1"

Make it executable:

bash
chmod +x .git/hooks/commit-msg

Hook Behavior ​

When you run git commit:

  1. Git creates the commit message file (.git/COMMIT_EDITMSG)
  2. The commit-msg hook runs with the file path as argument
  3. GitLint validates the message
  4. If valid (exit 0), the commit proceeds
  5. If invalid (exit 1), the commit is aborted

Example Workflow ​

bash
# Valid commit - proceeds normally
git commit -m "feat: add user authentication"
# [main abc1234] feat: add user authentication

# Invalid commit - aborted
git commit -m "added authentication"
# Error: Commit message does not follow conventional commit format
# Commit aborted

Integration Options ​

Using bun-git-hooks ​

GitLint works great with bun-git-hooks:

json
// package.json
{
  "git-hooks": {
    "pre-commit": {
      "staged-lint": {
        "*.{js,ts,json,yaml,yml,md}": "bunx --bun eslint . --fix"
      }
    },
    "commit-msg": "bunx gitlint .git/COMMIT_EDITMSG"
  }
}

Using simple-git-hooks ​

json
// package.json
{
  "simple-git-hooks": {
    "commit-msg": "npx gitlint $1"
  }
}

Using Husky ​

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

# Add commit-msg hook
echo 'npx gitlint "$1"' > .husky/commit-msg
chmod +x .husky/commit-msg

Using lefthook ​

yaml
# lefthook.yml
commit-msg:
  commands:
    gitlint:
      run: npx gitlint {1}

Uninstalling Hooks ​

Automatic Removal ​

bash
gitlint hooks --uninstall

Manual Removal ​

bash
rm .git/hooks/commit-msg

Bypassing Hooks ​

For emergencies, bypass the hook:

bash
git commit --no-verify -m "emergency fix"

Use sparingly! Invalid commits will still exist in history.

Shared Hook Configuration ​

Using package.json ​

Share hook configuration with your team:

json
{
  "scripts": {
    "prepare": "gitlint hooks --install"
  },
  "devDependencies": {
    "@stacksjs/gitlint": "^0.1.0"
  }
}

Team members get hooks automatically on npm install.

Using Git Templates ​

Set up hooks for all new repositories:

bash
# Create template directory
mkdir -p ~/.git-templates/hooks

# Create hook
cat > ~/.git-templates/hooks/commit-msg << 'EOF'
# !/bin/sh
npx gitlint "$1"
EOF

chmod +x ~/.git-templates/hooks/commit-msg

# Configure Git to use template
git config --global init.templateDir ~/.git-templates

Troubleshooting ​

Hook Not Running ​

Check if the hook exists and is executable:

bash
ls -la .git/hooks/commit-msg

Make it executable:

bash
chmod +x .git/hooks/commit-msg

Wrong gitlint Version ​

Ensure local installation is used:

bash
# Use npx/bunx to ensure local version
npx gitlint --version
bunx gitlint --version

Permission Denied ​

bash
# Fix permissions
chmod +x .git/hooks/commit-msg

Hook Output Not Visible ​

Some Git interfaces suppress hook output. Use verbose mode:

bash
# In the hook
gitlint --verbose "$1"

CI Integration ​

Also validate commits in CI to catch bypassed hooks:

yaml
# GitHub Actions

- name: Validate commit messages

  run: |
    git log --format=%B -n 1 | npx gitlint

See CI/CD Integration for more details.

Best Practices ​

  1. Always install hooks on setup

    bash
    npm install && npm run prepare
  2. Document hook requirements

    Add setup instructions to your README

  3. Use consistent configuration

    Commit gitlint.config.ts to the repository

  4. Combine with CI validation

    Hooks can be bypassed; CI provides backup validation

  5. Allow emergency bypass

    Document when --no-verify is acceptable

Next Steps ​