From be686a8d0d455a5926aba36532be0509c5c0aed5 Mon Sep 17 00:00:00 2001 From: Ethan <39577870+ethanndickson@users.noreply.github.com> Date: Thu, 9 Apr 2026 01:06:12 +1000 Subject: [PATCH] fix(scripts/githooks): clear all repo-local Git env vars in hooks (#24138) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem In linked worktrees, Git hooks inherit multiple repo-local environment variables: `GIT_DIR`, `GIT_COMMON_DIR`, `GIT_INDEX_FILE`, and others. The pre-commit and pre-push hooks only unset `GIT_DIR`, leaving the rest in place. When `make pre-commit` runs `go build`, Go tries to stamp VCS info by shelling out to `git`. With the leftover partial Git environment, `git` exits 128 and the build fails: ``` error obtaining VCS status: exit status 128 Use -buildvcs=false to disable VCS stamping. ``` This only happens inside hooks in a linked worktree — running `make pre-commit` directly from the terminal works fine because the repo-local vars are not set. ## Fix Replace the bare `unset GIT_DIR` in both hooks with a loop that clears every variable reported by `git rev-parse --local-env-vars`: ```sh while IFS= read -r var; do unset "$var" done < <(git rev-parse --local-env-vars) ``` This covers all 15 repo-local variables Git may inject (`GIT_DIR`, `GIT_COMMON_DIR`, `GIT_INDEX_FILE`, `GIT_OBJECT_DIRECTORY`, etc.) and is forward-compatible — if Git adds new local vars in the future, the loop picks them up automatically. --- scripts/githooks/pre-commit | 10 +++++++++- scripts/githooks/pre-push | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/scripts/githooks/pre-commit b/scripts/githooks/pre-commit index d04ba81479..2a0d9a4c46 100755 --- a/scripts/githooks/pre-commit +++ b/scripts/githooks/pre-commit @@ -14,7 +14,15 @@ set -euo pipefail cd "$(git rev-parse --show-toplevel)" -unset GIT_DIR + +# Unset all repo-local Git env vars, not just GIT_DIR. In linked +# worktrees the hook inherits variables like GIT_COMMON_DIR and +# GIT_INDEX_FILE that confuse child processes (notably Go's VCS +# stamping, which shells out to git and gets exit status 128). +# Process substitution (not a pipe) so unset runs in the current shell. +while IFS= read -r var; do + unset "$var" +done < <(git rev-parse --local-env-vars) # In linked worktrees, set worktree-scoped hooksPath to override shared config. if [[ "$(git rev-parse --git-dir)" != "$(git rev-parse --git-common-dir)" ]]; then diff --git a/scripts/githooks/pre-push b/scripts/githooks/pre-push index 6042f4898c..50f20f62e8 100755 --- a/scripts/githooks/pre-push +++ b/scripts/githooks/pre-push @@ -30,7 +30,15 @@ ALLOWLIST=( ) cd "$(git rev-parse --show-toplevel)" -unset GIT_DIR + +# Unset all repo-local Git env vars, not just GIT_DIR. In linked +# worktrees the hook inherits variables like GIT_COMMON_DIR and +# GIT_INDEX_FILE that confuse child processes (notably Go's VCS +# stamping, which shells out to git and gets exit status 128). +# Process substitution (not a pipe) so unset runs in the current shell. +while IFS= read -r var; do + unset "$var" +done < <(git rev-parse --local-env-vars) # In linked worktrees, set worktree-scoped hooksPath to override shared config. if [[ "$(git rev-parse --git-dir)" != "$(git rev-parse --git-common-dir)" ]]; then