Skip to content

ca971/git-templates

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

20 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ”§ git-templates

Universal Git hooks that work everywhere β€” zero config, any language, any project.

License: MIT Shell PRs Welcome

Production-grade git hooks that auto-detect your stack and enforce quality gates.
No frameworks. No dependencies. Pure Bash. Works on every git init and git clone.

Quick Install β€’ Features β€’ Supported Languages β€’ Configuration β€’ Skip Hooks


⚑ Quick Install

bash <(curl -fsSL https://raw.githubusercontent.com/ca971/git-templates/main/install.sh)

Or clone and install:

git clone https://github.com/ca971/git-templates.git
cd git-templates
bash install.sh

That's it. Every future git init and git clone will include the hooks automatically.


🎯 Features

4 hooks, 1 shared library

Hook When What it does
commit-msg On commit Validates Conventional Commits format
pre-commit On commit Quality gate β€” secrets, formatting, syntax, large files
pre-push On push Final gate β€” WIP detection, full lint, branch protection, tests
post-merge On pull/merge Smart summary β€” deps changes, version bumps, action items
_lib.sh Shared Colors, config system, skip logic, tool detection

What makes it different

βœ… Zero config         Works out of the box on ANY repo
βœ… Auto-detection      Only checks languages actually present
βœ… Fail gracefully     Missing tools = skip, never crash
βœ… Per-repo config     .githooks.conf for fine-tuning
βœ… 3 skip levels       Env var, config file, --no-verify
βœ… No dependencies     Pure Bash β€” no Node, no Python, no framework
βœ… Non-destructive     Warnings vs errors β€” you choose what blocks

🚦 What Gets Checked

commit-msg β€” Message validation

βœ“ Conventional Commits format (feat, fix, docs, chore, ...)
βœ“ Breaking change detection (! marker + BREAKING CHANGE footer)
βœ“ Subject length (configurable, default 72)
βœ“ Imperative mood ("add" not "added")
βœ“ No trailing period
βœ“ Body formatting (blank line separator, line length)
βœ“ Auto-skip: merge, revert, WIP/fixup commits
πŸ“Έ Example output
🚫 Invalid commit message format

  Expected: <type>(<scope>): <subject>

  Types:
    feat      New feature                    β†’ MINOR
    fix       Bug fix                        β†’ PATCH
    docs      Documentation only             β†’ PATCH
    refactor  Code restructuring             β†’ PATCH
    ...

  Your message: updated the readme

  Examples:
    feat(auth): add OAuth2 login flow
    fix(api): resolve null pointer on empty response
    docs: update installation guide

pre-commit β€” Quality gate

Universal checks (always active):
  βœ“ Debug markers (TODO, console.log, debugger, binding.pry, ...)
  βœ“ Backup/temp files (.bak, .swp, .old, ...)
  βœ“ Large files (> 5MB, configurable)
  βœ“ Secrets & credentials (API keys, tokens, passwords, AWS, GitHub, ...)
  βœ“ Merge conflict markers (<<<<<<<, =======, >>>>>>>)
  βœ“ .env files (should be gitignored)
  βœ“ Trailing whitespace

Language checks (auto-detected):
  βœ“ Lua        β†’ StyLua + syntax (LuaJIT/luac)
  βœ“ Python     β†’ Ruff / Black + syntax
  βœ“ JavaScript β†’ Prettier + ESLint
  βœ“ TypeScript β†’ Prettier + ESLint
  βœ“ Go         β†’ gofmt + go vet
  βœ“ Rust       β†’ rustfmt + Clippy
  βœ“ Shell      β†’ ShellCheck
  βœ“ YAML       β†’ yamllint
  βœ“ JSON       β†’ jq / python3
  βœ“ TOML       β†’ Taplo
  βœ“ Markdown   β†’ markdownlint
  βœ“ Dockerfile β†’ Hadolint
  βœ“ Terraform  β†’ terraform fmt
  βœ“ CSS/SCSS   β†’ Stylelint
πŸ“Έ Example output
πŸ” Pre-commit checks...
  βœ“ No debug markers
  βœ“ No backup files
  βœ“ No large files
  βœ“ No credentials detected
  βœ“ No merge conflict markers
  βœ“ No .env files
  βœ“ No trailing whitespace
   ── Language checks ──
  βœ“ StyLua formatting β€” 42 file(s)
  βœ“ Lua syntax (LuaJIT) β€” 42 file(s)
  βœ“ ShellCheck β€” 3 file(s)

βœ… All pre-commit checks passed

pre-push β€” Final gate

  βœ“ WIP/fixup/squash commit detection (blocks push)
  βœ“ Full language checks (same as pre-commit, all tracked files)
  βœ“ Tag validation (version file ↔ tag consistency)
  βœ“ Changelog entry check (on tag push)
  βœ“ Branch protection (interactive confirm on main/master/production)
  βœ“ Uncommitted changes warning
  βœ“ Test suite runner (opt-in, auto-detected)

post-merge β€” Smart summary

  βœ“ File changes breakdown (dynamic directory grouping with icons)
  βœ“ Dependency lockfile detection (22 package managers)
  βœ“ Version bump detection (10+ ecosystems)
  βœ“ Changelog updates
  βœ“ New / deleted files summary
  βœ“ Config change detection (Docker, CI, Terraform, Makefile, ...)
  βœ“ Actionable recommendations
  βœ“ Commit count & authors
πŸ“Έ Example output
╔══════════════════════════════════════════════════╗
β•‘  πŸ“‹ Post-merge summary                           β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

  Files changed: 23 total
    + 5 added
    ~ 16 modified
    - 2 deleted

  By area:
    πŸ“¦ src/              12 file(s)
    πŸ§ͺ tests/             5 file(s)
    πŸ€– .github/           3 file(s)
    πŸ“ config/            2 file(s)
    πŸ“„ (root)             1 file(s)

  πŸ“¦ Dependencies changed:
    package-lock.json (npm)

  🏷️  Version β†’ v2.1.0

  πŸ“‹ ## [2.1.0] β€” 2025-01-15

  πŸ“Œ Recommended actions:
    1. npm install
    2. Review build targets

  ─────────────────────────────────────────────
  8 commit(s) merged
  Authors: Alice, Bob

βœ… Merge complete

🌍 Supported Languages

Language Formatter Linter Syntax Check
Lua StyLua β€” LuaJIT / luac
Python Ruff / Black Ruff py_compile
JavaScript Prettier ESLint β€”
TypeScript Prettier ESLint tsc --noEmit
Go gofmt go vet go build
Rust rustfmt Clippy cargo check
Shell β€” ShellCheck β€”
YAML β€” yamllint β€”
JSON β€” β€” jq / python3
TOML Taplo β€” β€”
Markdown β€” markdownlint β€”
Dockerfile β€” Hadolint β€”
Terraform terraform fmt terraform validate β€”
CSS/SCSS β€” Stylelint β€”

No tool installed? No problem. Checks are skipped gracefully β€” never crash, never block.

πŸ“¦ Recognized Lockfiles (post-merge)

22 package managers
Lockfile Manager Action
package-lock.json npm npm install
yarn.lock Yarn yarn install
pnpm-lock.yaml pnpm pnpm install
bun.lockb Bun bun install
requirements.txt pip pip install -r requirements.txt
Pipfile.lock Pipenv pipenv install
poetry.lock Poetry poetry install
uv.lock uv uv sync
Gemfile.lock Bundler bundle install
composer.lock Composer composer install
go.sum Go modules go mod download
Cargo.lock Cargo cargo build
mix.lock Mix mix deps.get
pubspec.lock Flutter/Dart flutter pub get
Podfile.lock CocoaPods pod install
flake.lock Nix nix flake update
lazy-lock.json lazy.nvim :Lazy sync
build.zig.zon Zig zig build
pdm.lock PDM pdm install
packages.lock.json .NET dotnet restore

βš™οΈ Configuration

Per-repo: .githooks.conf

Place a .githooks.conf at your repo root to customize behavior:

# Example: Python API project
[commit-msg]
subject_max_length = 72
strict_warnings = true        # warnings block commit

[pre-commit]
max_file_size = 10485760      # 10MB
debug_markers_block = true
disable = prettier,eslint     # not a JS project

[pre-push]
protected_branches = main,staging,production
run_tests = true
test_command = pytest -q -x
disable = prettier,eslint

[post-merge]
show_stat = true
max_files_shown = 15

Quick start configs

πŸ“ Docs/Notes repo
[pre-commit]
disable = stylua,shellcheck,ruff,eslint,prettier,gofmt,rustfmt
[pre-push]
disable = stylua,lua-syntax,ruff,eslint,prettier,tsc,gofmt,govet,rustfmt,cargo-check
πŸŒ™ Neovim plugin (Lua)
[pre-commit]
debug_markers_block = true
[pre-push]
run_tests = false
βš›οΈ React/Next.js app
[pre-push]
run_tests = true
test_command = npm test -- --watchAll=false
protected_branches = main,staging
πŸ¦€ Rust project
[pre-push]
run_tests = true
test_command = cargo test --quiet
🐹 Go service
[pre-push]
run_tests = true
test_command = go test ./...
protected_branches = main,production

Config reference

Section Key Default Description
[global] skip_all false Disable all hooks for this repo
[commit-msg] skip false Skip this hook
subject_max_length 72 Max subject line length
body_max_length 100 Max body line length
strict_warnings false Warnings become errors
[pre-commit] skip false Skip this hook
max_file_size 5242880 Max file size in bytes (5MB)
debug_markers_block false Debug markers become errors
trailing_ws_block false Trailing whitespace becomes error
disable (empty) Comma-separated checkers to skip
[pre-push] skip false Skip this hook
protected_branches main,master,production,release,staging Branches requiring confirmation
allow_wip false Allow WIP commits to be pushed
run_tests false Run test suite before push
test_command (auto) Custom test command
disable (empty) Comma-separated checkers to skip
[post-merge] skip false Skip this hook
show_stat true Show git diff --stat
max_files_shown 10 Max files in stat output

⏭️ Skip Hooks

Three levels of escape hatches:

# Skip ALL hooks (one-time)
SKIP_HOOKS=1 git commit -m "feat: emergency fix"
SKIP_HOOKS=1 git push

# Skip SPECIFIC hook (one-time)
SKIP_COMMIT_MSG=1 git commit -m "wip"
SKIP_PRE_COMMIT=1 git commit
SKIP_PRE_PUSH=1 git push
SKIP_POST_MERGE=1 git pull

# Git native (skips pre-commit + commit-msg)
git commit --no-verify
git push --no-verify

# Permanent skip for a repo (.githooks.conf)
# [pre-commit]
# skip = true

πŸ”„ Managing Hooks

# Check installation status
bash install.sh --check

# Update to latest version
bash install.sh --update

# Uninstall completely
bash install.sh --uninstall

# Inject hooks into existing repo
cd your-existing-repo && git init   # safe β€” won't erase anything

# Inject into ALL repos under a directory
find ~/Projects -name ".git" -type d -maxdepth 3 -exec dirname {} \; | \
    xargs -I{} sh -c 'cd "{}" && git init'

Injection in existing repos

# Bonus script : Inject in ALL your existing repos
inject-hooks() {
    local dir="${1:-$HOME/Projects}"
    find "$dir" -name ".git" -type d -maxdepth 3 2>/dev/null | while read -r gitdir; do
        repo=$(dirname "$gitdir")
        echo -e "  β†’ ${repo}"
        (cd "$repo" && git init) 2>/dev/null
    done
    echo -e "\nβœ… Done"
}

# Usage:
inject-hooks ~/Projects

Useful aliases (.zshrc / .bashrc)

# ── Git hooks shortcuts ───────────────────────────────────────
alias ghcheck='bash ~/.git-templates/install.sh --check'
alias ghupdate='bash ~/.git-templates/install.sh --update'

# Skip shortcuts
alias gc!='SKIP_HOOKS=1 git commit'
alias gp!='SKIP_HOOKS=1 git push'

# Reinject hooks in current repo
alias ghinit='git init'  # safe β€” just copies hooks

# Edit hooks config for current repo
alias ghconf='${EDITOR:-vim} .githooks.conf'
alias ghconf-init='cp ~/.git-templates/githooks.conf.example .githooks.conf && ${EDITOR:-vim} .githooks.conf'

πŸ—οΈ Architecture

~/.git-templates/hooks/
β”œβ”€β”€ _lib.sh         Shared foundation
β”‚                   β”œβ”€β”€ Colors & formatting
β”‚                   β”œβ”€β”€ Tool detection (command_exists)
β”‚                   β”œβ”€β”€ File detection (staged/tracked by extension)
β”‚                   β”œβ”€β”€ Config system (.githooks.conf parser)
β”‚                   β”œβ”€β”€ Skip logic (3 levels)
β”‚                   └── Checker registry (enable/disable)
β”‚
β”œβ”€β”€ commit-msg      Conventional Commits enforcement
β”‚                   └── Format β†’ Type β†’ Length β†’ Mood β†’ Body
β”‚
β”œβ”€β”€ pre-commit      Quality gate (staged files only = fast)
β”‚                   β”œβ”€β”€ Universal: secrets, large files, markers, .env
β”‚                   └── Language: 14 auto-detected ecosystems
β”‚
β”œβ”€β”€ pre-push        Final gate (all tracked files)
β”‚                   β”œβ”€β”€ WIP/fixup detection
β”‚                   β”œβ”€β”€ Language checks (full scan)
β”‚                   β”œβ”€β”€ Tag ↔ version consistency
β”‚                   β”œβ”€β”€ Branch protection
β”‚                   └── Test runner (opt-in)
β”‚
└── post-merge      Intelligence (informational, never blocks)
                    β”œβ”€β”€ Dynamic file breakdown
                    β”œβ”€β”€ 22 lockfile detections
                    β”œβ”€β”€ Version bump detection
                    └── Actionable recommendations

πŸš₯ Features

β”œβ”€β”€ hooks/
β”‚   β”œβ”€β”€ _lib.sh            ← Shared: colors, config, skip, detection
β”‚   β”œβ”€β”€ commit-msg         ← Conventional commits (universal)
β”‚   β”œβ”€β”€ pre-commit         ← Quality gate (14 languages)
β”‚   β”œβ”€β”€ post-merge         ← Post-pull intelligence (22 lockfiles)
β”‚   └── pre-push           ← Final gate (6 languages + tests + tags)
β”œβ”€β”€ githooks.conf.example  ← Configuration template
└── install.sh             ← One-command installer
  • βœ… 14 languages auto-detected
  • βœ… 22 lockfiles recognized
  • βœ… 10+ versioning formats supported
  • βœ… 3 skip levels (env / config / global)
  • βœ… Per-repo deactivatable checkers
  • βœ… Zero-crash design on empty or minimal repos
  • βœ… Full lifecycle: install / update / uninstall / check
  • βœ… Automatic backup before every update

🀝 Contributing

PRs welcome! Some ideas:

  • Add support for more languages (Kotlin, Swift, Dart, Zig, ...)
  • Add pre-rebase hook
  • Add prepare-commit-msg hook (auto-prefix with branch name)
  • Performance benchmarks
  • Fish shell support

πŸ“„ License

MIT β€” Use it, fork it, make it yours.


Made with πŸ”§ by ca971

If this saves you time, ⭐ the repo!

About

πŸ”§ Universal Git hooks template β€” production-grade quality gates for any project. Auto-detected language checks, secrets scanning, conventional commits, and more. Zero config, works everywhere.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages