Git 2.54: Config-Based Hooks Replace Husky and Pre-Commit
Canonical version: Git 2.54: Config-Based Hooks Replace Husky and Pre-Commit.
Git 2.54 ships config-based hooks — the single most practical improvement in years for teams that care about code quality gates. If you've been managing Husky config files, pre-commit YAML, or manually copying hook scripts across repos, this replaces all of it.
What changed
Previously, git hooks lived only as executable scripts inside .git/hooks/. That folder is not tracked, not shareable, and not composable. Every tool in the ecosystem (Husky, pre-commit, Lefthook, etc.) existed to paper over this limitation.
Git 2.54 introduces configuration-based hooks. Define hooks in any git config file:
[hook "linter"]
event = pre-commit
command = ~/bin/linter --cpp20
This works in:
~/.gitconfig— applies to every repo on your machine/etc/gitconfig— system-wide, for all users- The repo's local
.git/configor any included config file
Multiple hooks for the same event are supported and run in config-file order. The legacy hook scripts in .git/hooks/ still work and run last, so nothing breaks.
Management commands
# See all hooks configured for an event and where they come from
git hook list pre-commit
# Disable a hook without deleting it
git config hook.linter.enabled false
The git hook list output shows each hook's source (global, local, system), so you know exactly what runs and why.
What this replaces
- Husky: npm package that installs hook shims into
.git/hooks/. Requirespackage.json, runs only in Node projects. - pre-commit: Python-based hook manager with its own YAML config format and plugin ecosystem. Works across languages but requires Python + pip.
- Lefthook, Overcommit, and every other third-party hook manager: all workarounds for the same underlying limitation.
With config-based hooks, you get the same capability with zero extra dependencies and zero extra config formats. A single ~/.gitconfig stanza and every repo on your machine benefits.
Practical setup
Enable a linter for every project without touching a single repo:
# ~/.gitconfig
[hook "style-check"]
event = pre-commit
command = ~/.local/bin/my-linter
[hook "security-scan"]
event = pre-push
command = ~/.local/bin/secret-scanner
To opt a specific repo out of the global hook:
# .git/config (repo-local)
[hook "security-scan"]
enabled = false
Other notable changes in 2.54
git history(experimental):git history reword <commit>andgit history split <commit>for targeted history rewriting without interactive rebase.- Geometric repacking by default:
git maintenance runnow uses the geometric strategy, avoiding expensive full repacks. git add -pimprovements: shows previous hunk decisions; adds--no-auto-advanceflag.git replayupgrades: atomic reference updates,--revertmode, root commit support.- HTTP 429 handling: new
http.retryAfterconfig for rate-limited servers. git log -L+ pickaxe:-Lnow works with-S,-G, and other diff filters.
References
Related
About Sébastien
Ready to get to the next level?
Found this valuable? Share it with someone who needs it.