- Shell 44.3%
- Python 35.6%
- CSS 14.8%
- Makefile 5.3%
git-tools
Personal Git hooks and workflow tools for safer, cleaner commits.
Overview
git-tools is a small CLI and hook collection for installing reusable Git
workflow guardrails. It provides a Gitleaks pre-commit hook, a Python-backed
commit-msg validator, a commit message template, installer smoke tests, and
optional agent guidance for safer git commit commands.
Use it when you want the same commit hygiene checks across personal projects or
when you need to copy managed hooks into a repository's .git/hooks directory.
Features
- Scan staged changes for leaked secrets with Gitleaks before commits.
- Enforce structured commit messages with a
commit-msghook. - Provide a reusable commit message template.
- Install hooks and gitmessage globally, locally, or by copying into a repo.
- Target another repository with
--repo PATHfor local installs. - Ship installable agent guidance for hook-friendly commit commands.
- Run local diagnostics, fixture tests, and installer smoke tests.
Requirements
- Git
- POSIX-compatible shell
- Python 3.10+
- Gitleaks, required for the
pre-commithook. Install it from https://github.com/gitleaks/gitleaks.
Quick Start
Clone the repository somewhere stable:
git clone https://codeberg.org/rch/git-tools.git ~/.local/share/git-tools
Install hooks and the gitmessage template globally by linked configuration:
~/.local/share/git-tools/bin/git-tools --install --hooks --gitmessage --global
Check the installation:
~/.local/share/git-tools/bin/doctor
Linked install is the default. Git points at files in this checkout, so future
updates to git-tools apply without reinstalling.
Command Reference
git-tools [--install|--uninstall] [--hooks] [--gitmessage] [--global|--local] [--copy] [--repo PATH]
| Option | Description |
|---|---|
--install |
Install selected targets. This is the default, but examples show it explicitly. |
--uninstall |
Remove selected targets. |
--hooks |
Install or uninstall Git hooks. |
--gitmessage |
Install or uninstall the commit message template. |
--global |
Use global Git config. This is the default scope. |
--local |
Use local Git config for the current repository. |
--copy |
Copy files into the local repository. Requires --local. |
--repo PATH |
Target another local Git repository. Requires --local. |
Choose at least one target: --hooks, --gitmessage, or both.
Installation Modes
Linked Install
Linked install configures Git to use hooks and templates directly from this
git-tools checkout.
Install hooks and gitmessage globally for all repositories:
~/.local/share/git-tools/bin/git-tools --install --hooks --gitmessage --global
Install hooks and gitmessage for one repository only:
cd /path/to/project
~/.local/share/git-tools/bin/git-tools --install --hooks --gitmessage --local
Install hooks and gitmessage for another repository without changing directories:
~/.local/share/git-tools/bin/git-tools --install --hooks --gitmessage --local --repo /path/to/project
Install only hooks:
~/.local/share/git-tools/bin/git-tools --install --hooks --local
Install only gitmessage:
~/.local/share/git-tools/bin/git-tools --install --gitmessage --local
Copied Local Install
Copied install writes selected files into the target repository. Hooks are
copied to .git/hooks/; gitmessage is copied to .gitmessage and configured
with git config --local commit.template .gitmessage.
Copy hooks and gitmessage:
cd /path/to/project
~/.local/share/git-tools/bin/git-tools --install --hooks --gitmessage --local --copy
Copy hooks and gitmessage to another repository without changing directories:
~/.local/share/git-tools/bin/git-tools --install --hooks --gitmessage --local --copy --repo /path/to/project
Copy only hooks:
cd /path/to/project
~/.local/share/git-tools/bin/git-tools --install --hooks --local --copy
Copy only gitmessage:
cd /path/to/project
~/.local/share/git-tools/bin/git-tools --install --gitmessage --local --copy
Copy mode does not change core.hooksPath. If core.hooksPath is set, Git may
not run hooks copied to .git/hooks, and the installer prints a warning.
Copy mode refuses to overwrite existing pre-commit or commit-msg hooks
unless they were previously installed by git-tools. It also upgrades the
legacy unmarked git-tools pre-commit hook that only runs the default Gitleaks
scan. Copied hooks and gitmessage include a compact git-tools version in the
managed-file comment.
The copied commit-msg hook still calls the validator from this git-tools
checkout, so moving or deleting the checkout requires reinstalling.
Compatibility Wrappers
The old wrapper scripts still work and install or uninstall both hooks and gitmessage by default:
~/.local/share/git-tools/bin/install-hooks --local --copy
~/.local/share/git-tools/bin/uninstall-hooks --local --copy
Use --no-template with install-hooks to install only hooks.
Agent Commit Skill
The bundled git-commit-guidance skill gives agents global guidance for safe
Git commits, hook-friendly message bodies, and correct git commit -m wrapping.
Install it globally:
make install-skill
Install into a custom skill directory:
SKILLS_DIR=/path/to/skills make install-skill
Remove it later:
make uninstall-skill
Uninstall
Remove global linked hook and gitmessage configuration:
~/.local/share/git-tools/bin/git-tools --uninstall --hooks --gitmessage --global
Remove local linked hooks only:
cd /path/to/project
~/.local/share/git-tools/bin/git-tools --uninstall --hooks --local
Remove copied hooks and gitmessage from one repository:
cd /path/to/project
~/.local/share/git-tools/bin/git-tools --uninstall --hooks --gitmessage --local --copy
Remove copied hooks and gitmessage from another repository:
~/.local/share/git-tools/bin/git-tools --uninstall --hooks --gitmessage --local --copy --repo /path/to/project
Copied uninstall only removes files that contain the git-tools install marker.
Check Installation
~/.local/share/git-tools/bin/doctor
bin/doctor prints Git, Python, Gitleaks, core.hooksPath,
commit.template, and any local copied hook or template files when run inside a
Git repository.
Hooks
hooks/pre-commit
Runs Gitleaks against staged changes:
gitleaks git --pre-commit --staged --no-banner --no-color --verbose --redact
To use a custom Gitleaks config, set GITLEAKS_CONFIG:
GITLEAKS_CONFIG=/path/to/gitleaks.toml git commit
The file config/gitleaks.toml is provided as a place to keep shared custom
rules, allowlists, or future Gitleaks configuration.
The pre-commit hook scans only staged changes so commits stay fast and focused. To audit existing repository history, run a full Gitleaks scan manually:
gitleaks git --no-banner --no-color --verbose --redact
Run a full scan before public releases or after importing commits that may have been created without these hooks.
hooks/commit-msg
Runs the Python validator in lib/git_tools/commit_msg_check.py.
The validator expects commit messages in this general form:
<type>(<scope>)!: <subject>
<body explaining why the change is needed>
<footer>
The scope and ! marker are optional, but breaking-change commits must include
both ! in the title and a BREAKING CHANGE: footer.
Commit Message Rules
Allowed commit types:
feat, fix, refactor, perf, docs, test, build, ci, chore, style, revert
Subject rules:
- Maximum 50 characters.
- Must start with a capital letter.
- Must not end with a period.
- Must start with one of the recommended imperative verbs configured in the validator.
Body rules:
- Body is required by default.
- Body lines must be 72 characters or shorter.
- The body should explain why the change is needed, not just what changed.
- Leading and trailing blank lines are ignored, matching Git's cleanup of editor/template padding around the commit message.
- When using
git commit -m, pass a wrapped body as one body-margument with literal newlines. Git treats repeated body-mflags as separate paragraphs. - Do not use one
-mper wrapped body line; use one multi-line body-morgit commit -F -with a heredoc.
Footer rules:
BREAKING CHANGE: <details>
Closes: #123
Refs: #123
Refs: PR #123
Refs: #123 / PR #456
Co-authored-by: Name <email@example.com>
Footer lines must be 72 characters or shorter.
Examples
Valid commit message:
feat(auth): Add password reset flow
Explain why account recovery is needed and how this improves
support outcomes without changing existing login behavior.
Closes: #123
Valid breaking-change commit:
feat(api)!: Rename user identifier field
Explain why the API field needs to change and how clients should
migrate safely during the next release window.
BREAKING CHANGE: Rename user_id to account_id in API responses.
Invalid subject-only commit, because the body is required:
fix(auth): Fix password reset redirect
Testing
Run the commit-message validator fixtures:
make test
Run all local checks before committing:
make verify
Show available Make targets:
make help
Useful targets:
| Target | Description |
|---|---|
make lint |
Check shell script syntax with sh -n. |
make test |
Run the commit-message validator fixtures. |
make test-commit-msg |
Run the commit-message validator fixtures directly. |
make smoke-test |
Check copy install and uninstall flows in a temporary repo. |
make install-skill |
Install the git-commit-guidance skill. |
make uninstall-skill |
Remove the git-commit-guidance skill. |
make verify |
Run lint, test, and smoke-test. |
The Makefile is a thin task runner. Test logic lives in scripts under bin/,
so checks can also be run directly:
bin/test-commit-msg
bin/test-smoke
Commit-message fixtures live in tests/commit-msg/:
- Put valid examples in
tests/commit-msg/valid/*.txt. - Put invalid examples in
tests/commit-msg/invalid/*.txt. - Each fixture is a full commit message, not just a subject line.
After adding or changing fixtures, run:
make test-commit-msg
Project Structure
High-level layout:
git-tools/
|-- assets/ README branding assets
|-- bin/ CLI entrypoints and test scripts
|-- config/ Shared Gitleaks configuration placeholder
|-- hooks/ Source hooks for linked and copied installs
|-- lib/ Python commit message validator
|-- scripts/ Skill install and uninstall helpers
|-- skills/ Installable agent guidance
|-- templates/ Source commit message template
`-- tests/ Commit-message validator fixtures
Forgejo Actions CI lives in .forgejo/workflows/verify.yml and runs
make verify.
Local Hooks Are Guardrails
Local Git hooks can usually be bypassed with git commit --no-verify. Treat
these hooks as a developer-experience guardrail, not as the only enforcement
layer. For shared repositories, run important checks again in CI or server-side
hooks.
License
This project is licensed under the MIT License. See LICENSE for details.