mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
be686a8d0d
## 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.
49 lines
1.6 KiB
Bash
Executable File
49 lines
1.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Pre-commit hook that runs CI-equivalent checks locally.
|
|
# Classifies staged files by type and only runs relevant make
|
|
# targets. Falls back to the full `make pre-commit` when the
|
|
# Makefile changed or CODER_HOOK_RUN_ALL=1 is set.
|
|
#
|
|
# Installation (worktree-compatible):
|
|
#
|
|
# git config core.hooksPath scripts/githooks
|
|
#
|
|
# Bypass: git commit --no-verify
|
|
|
|
set -euo pipefail
|
|
|
|
cd "$(git rev-parse --show-toplevel)"
|
|
|
|
# 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
|
|
git config --worktree core.hooksPath scripts/githooks
|
|
fi
|
|
|
|
if [[ ${CODER_HOOK_RUN_ALL:-} == 1 ]]; then
|
|
exec make pre-commit
|
|
fi
|
|
|
|
staged=$(git diff --cached --name-only --diff-filter=d)
|
|
if [[ -z $staged ]]; then
|
|
echo "pre-commit: no staged changes, skipping"
|
|
exit 0
|
|
fi
|
|
|
|
# If Go, TS, or build-system files changed, run the full
|
|
# pre-commit. Otherwise run the lightweight target that
|
|
# covers everything except gen, Go/TS fmt+lint, and binary build.
|
|
if echo "$staged" | grep -qE '\.(go|ts|tsx|sql|proto)$|^go\.(mod|sum)$|^site/|^Makefile$'; then
|
|
exec make pre-commit
|
|
fi
|
|
exec make pre-commit-light
|