This project uses Git hooks to automate code quality checks and improve the developer experience. The hooks are automatically configured when you run ./configure.
The repository includes three Git hooks that run automatically during the commit process:
- pre-commit - Formats and lints shell scripts before committing
- prepare-commit-msg - Auto-formats commit messages with conventional commits
- commit-msg - Sends a macOS notification when commit succeeds
When you run ./configure, it automatically:
- Installs all required dependencies (via Brewfile on macOS)
- Configures Git to use the
githooks/directory - Makes all hooks executable
./configureThe setup uses Git's include.path feature to load .gitconfig, which sets:
[core]
hooksPath = githooksThis means:
- ✅ Hooks are versioned in the repository
- ✅ Updates to hooks are automatically pulled with
git pull - ✅ All developers use the same hooks
Purpose: Automatically format and lint shell scripts before committing.
What it does:
- Detects modified shell files (
.sh,.bash,badgetizr,configure) - Runs
shfmtto auto-format code - Stages the formatted changes automatically
- Runs
shellcheckto catch issues - Sends a macOS notification on failure
Dependencies:
shfmt- Shell script formattershellcheck- Shell script linter
Example output:
🟡 Checking 3 shell file(s)...
🟡 Running shfmt formatter...
🟢 Auto-formatted 2 file(s) and staged changes
- badgetizr
- utils.sh
🟡 Running shellcheck linter...
🟢 ShellCheck passed
🟢 Pre-commit checks passed
On failure:
🟡 Running shellcheck linter...
🔴 ✗ ShellCheck found issues:
In utils.sh line 42:
echo $variable
^-- SC2086: Double quote to prevent globbing
🟡 Please fix the issues above before committing.
Purpose: Automatically format commit messages following conventional commits.
What it does:
- Detects your branch name (e.g.,
feat/GH-123_add-feature) - Extracts the commit type (
feat,fix,docs, etc.) - Extracts the GitHub issue number (
GH-123) - Prepares your commit message:
feat(GH-123): #write description here
Supported commit types:
feat- New featurefix- Bug fixdocs- Documentation changesstyle- Code style changesrefactor- Code refactoringperf- Performance improvementstest- Adding testsbuild- Build system changesci- CI/CD changeschore- Other changesrevert- Reverting changes
Branch naming convention:
<type>/GH-<number>_description
Examples:
feat/GH-123_add-user-authfix/GH-456_resolve-crashdocs/GH-789_update-readme
Commit message format:
<type>(GH-<number>): <description>
Examples:
feat(GH-123): add user authentication systemfix(GH-456): resolve crash on startupdocs(GH-789): update README with installation steps
Special behavior:
- Amend commits: Preserves existing message (already validated)
- Non-conventional branches: Lets you write message normally
- Placeholder:
#write description herereminds you to add description
Purpose: Sends a macOS notification when commit succeeds.
What it does:
- Reads your commit message
- Sends a notification with the commit summary
- Plays a success sound
Example notification:
Title: Badgetizr Commit Successful
Message: feat(GH-123): add user authentication system
Sound: Glass
Requirements:
- macOS only
terminal-notifier(installed via Brewfile)
All dependencies are installed automatically with brew bundle:
brew "gh" # GitHub CLI
brew "glab" # GitLab CLI
brew "yq" # YAML processor
brew "jq" # JSON processor
brew "shellcheck" # Shell linter
brew "shfmt" # Shell formatter
brew "bats-core" # Testing framework
brew "kcov" # Code coverage
brew "terminal-notifier" # macOS notificationsOn Linux, gh, glab, shellcheck, and shfmt must be installed manually (see ./configure output for instructions).
If hooks aren't executing:
- Verify Git configuration:
git config --local --get-all include.path
# Should output: .gitconfig- Check hooks path:
git config --local core.hooksPath
# Should output: githooks- Re-run configure:
./configureIf you see:
🔴 Error: Missing required dependencies: shfmt shellcheck
🟡 Please run './configure' at the root of the project
Solution:
./configureIf hooks exist but don't run:
chmod +x githooks/*In rare cases where you need to bypass hooks:
git commit --no-verify -m "emergency fix"Warning: This skips all quality checks. Use sparingly.
To disable a hook temporarily, rename it:
mv githooks/pre-commit githooks/pre-commit.disabledRe-enable:
mv githooks/pre-commit.disabled githooks/pre-commitHooks are versioned in githooks/. To modify:
- Edit the hook file (e.g.,
githooks/pre-commit) - Test locally
- Commit and push
- Other developers get updates on next
git pull
Git supports many hook types. To add a new hook:
- Create file in
githooks/(e.g.,githooks/post-checkout) - Make it executable:
chmod +x githooks/post-checkout - Commit and push
Available hooks:
pre-push- Before pushingpost-checkout- After checking out a branchpost-merge- After merging- See: https://git-scm.com/docs/githooks
- Always run
./configureafter cloning - Sets up hooks and dependencies - Follow branch naming convention - Enables automatic commit formatting
- Don't use
--no-verifyunless absolutely necessary - Hooks ensure quality - Keep hooks fast - They run on every commit
- Test hooks thoroughly - They affect all developers
- Keep error messages clear - Help developers fix issues quickly
- Update this documentation - When adding/modifying hooks
- Consider hook performance - Slow hooks frustrate developers
# Clone and setup
git clone <repo>
cd homebrew-badgetizr
./configure
# Create feature branch
git checkout -b feat/GH-123_add-badges
# Make changes
vim badgetizr
# Commit (hooks run automatically)
git add badgetizr
git commit
# Editor opens with: feat(GH-123): #write description here
# Replace placeholder with: feat(GH-123): add dynamic badge support
# Save and close
# If shfmt auto-formatted files, they're already staged
# If shellcheck fails, fix issues and commit againSuccess case:
🟡 Checking 2 shell file(s)...
🟡 Running shfmt formatter...
🟢 Auto-formatted 1 file(s) and staged changes
- providers/github.sh
🟡 Running shellcheck linter...
🟢 ShellCheck passed
🟢 Pre-commit checks passed
Failure case:
🟡 Checking 1 shell file(s)...
🟡 Running shfmt formatter...
🟡 Running shellcheck linter...
🔴 ✗ ShellCheck found issues:
In badgetizr line 145:
if [ $status == 0 ]; then
^-- SC2086: Double quote to prevent globbing
^-- SC2039: In POSIX sh, == in place of = is undefined
🟡 Please fix the issues above before committing.