From ae04627b43b4d533088b8a389e5462efed2ae8f6 Mon Sep 17 00:00:00 2001 From: sommerfeld Date: Tue, 19 May 2026 16:50:52 +0100 Subject: refactor(git): use classic .git/hooks/ for per-clone override MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switch the dispatcher's per-clone override location from the bespoke .git/hooks-local/ to the classic .git/hooks/. This is: - The untracked location git has used since forever, so no new convention to learn. - Where husky, lefthook, pre-commit-the-tool, and most other hook managers install by default — they now "just work" again under our global core.hooksPath. git init's *.sample files don't collide because the dispatcher only matches the exact hook name and the executable bit. The only behavior change is that a forgotten legacy .git/hooks/pre-commit from before core.hooksPath was set will start running again — that's arguably restoring expected git semantics, not a regression. --- dot_config/git/hooks/_dispatch.sh | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'dot_config') diff --git a/dot_config/git/hooks/_dispatch.sh b/dot_config/git/hooks/_dispatch.sh index 0b1135d..ed5acbf 100644 --- a/dot_config/git/hooks/_dispatch.sh +++ b/dot_config/git/hooks/_dispatch.sh @@ -4,13 +4,12 @@ # hook can do its own work after. # # Lookup order (first executable file wins): -# 1. `/hooks-local/` — untracked per-clone override, -# lives inside .git/ so it stays personal. Use this when you want -# to replace a tracked .githooks/ on a shared repo without -# affecting teammates. Create with e.g.: -# $ mkdir -p "$(git rev-parse --git-dir)/hooks-local" -# $ $EDITOR "$(git rev-parse --git-dir)/hooks-local/pre-commit" -# $ chmod +x "$(git rev-parse --git-dir)/hooks-local/pre-commit" +# 1. `/hooks/` — the classic, untracked per-clone +# hook location. Already where tools like husky / lefthook / +# pre-commit install. Drop a script here to override a tracked +# .githooks/ on a shared repo without affecting teammates. +# `git init`'s `*.sample` files don't match by name, so they're +# ignored — no collision. # 2. `/.githooks/` — tracked, the project's # shared hook. The intended default for opting a repo in. # @@ -19,8 +18,8 @@ # global logic afterwards. # # GIT_HOOK_DISPATCHED guards against re-entry: if some legacy repo has -# its own `.githooks/` that ends with `exec "$HOME/.config/..."` -# (the old stub pattern), we won't dispatch back into it a second time. +# its own hook that ends with `exec "$HOME/.config/..."` (the old stub +# pattern), we won't dispatch back into it a second time. # shellcheck shell=sh dispatch_repo_hook() { @@ -32,7 +31,7 @@ dispatch_repo_hook() { gitdir=$(git rev-parse --git-dir 2>/dev/null) || return 0 root=$(git rev-parse --show-toplevel 2>/dev/null) || return 0 - for candidate in "$gitdir/hooks-local/$hookname" "$root/.githooks/$hookname"; do + for candidate in "$gitdir/hooks/$hookname" "$root/.githooks/$hookname"; do if [ -x "$candidate" ]; then GIT_HOOK_DISPATCHED=1 "$candidate" "$@" rc=$? -- cgit v1.3.1