fix(githooks): use absolute-git-dir to find worktree in post-receive

`git rev-parse --show-toplevel` in hook context (cwd=GIT_DIR, GIT_DIR
set) returns the .git path itself without erroring, so the previous
`|| echo $PWD` fallback never triggered and the script silently
cd'd into .git/.

Use `git rev-parse --absolute-git-dir` to reliably get the absolute
git-dir, then its parent is the worktree root. This works in both
interactive shells and hook context.
This commit is contained in:
2026-06-16 15:58:38 +08:00
parent b09e2d093d
commit db350aae44
+10 -1
View File
@@ -7,8 +7,17 @@ export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
REPO_TOPLEVEL="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")"
# git 调钩子时 cwd=GIT_DIR。此时 `git rev-parse --show-toplevel` 返回
# `/.../repo/.git`(不报错,所以原版的 `|| echo $PWD` 退路不会触发),
# 会让 cd 误进 .git 目录。安全办法:拿绝对 git-dir 路径,取其父目录。
GIT_DIR_ABS="$(git rev-parse --absolute-git-dir 2>/dev/null)"
if [ -n "$GIT_DIR_ABS" ] && [ -d "$GIT_DIR_ABS" ]; then
REPO_TOPLEVEL="$(cd "$GIT_DIR_ABS/.." && pwd)"
else
REPO_TOPLEVEL="$(git rev-parse --show-toplevel 2>/dev/null || echo "$PWD")"
fi
cd "$REPO_TOPLEVEL" || { echo "FATAL: cannot cd to $REPO_TOPLEVEL" >&2; exit 1; }
echo "=== REPO_TOPLEVEL=$REPO_TOPLEVEL (GIT_DIR_ABS=$GIT_DIR_ABS) ===" >&2
# ============================================================
# 0. sync_worktree —— 将工作树同步到新 push 的 HEAD