Skip to content

Commit 80290f8

Browse files
authored
Merge pull request #472 from Chris0Jeky/chore/windows-git-hardening
OPS: Harden Windows Git resolution and index.lock reliability
2 parents 9e59ba4 + c4e61ff commit 80290f8

File tree

3 files changed

+101
-4
lines changed

3 files changed

+101
-4
lines changed

AGENTS.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,10 @@ Its scope applies to the entire repo unless overridden by more specific `AGENTS.
6161
- For product-facing slices, ensure issue scope and acceptance criteria explicitly align with the current thesis (reduce maintenance overhead/capture friction and preserve review-first trust).
6262

6363
### Windows Git Reliability Fallback
64-
- If `git` resolves to Cygwin or produces signal/pipe-style failures, use `C:\Program Files\Git\cmd\git.exe` explicitly for repo operations.
64+
- Run `bash scripts/check-git-env.sh` at the start of a session to validate git resolution and index.lock state.
65+
- If `git` resolves to Cygwin or produces signal/pipe-style failures, use `C:\Program Files\Git\cmd\git.exe` explicitly for repo operations (or add `C:\Program Files\Git\cmd` to the front of `PATH`).
6566
- When running automated commits in the background terminal, ALWAYS append `--no-gpg-sign` and `--no-verify` to `git commit` to prevent hidden GPG pinentry prompts from freezing the process.
66-
- If a commit fails because `.git/index.lock` cannot be created, first check for active `git` processes; remove `.git/index.lock` only when no git process is running.
67+
- If a commit fails because `.git/index.lock` cannot be created, first check for active `git` processes; remove `.git/index.lock` only when no git process is running. The `check-git-env.sh` script automates this detection.
6768
- For stacked branches with small conflict surfaces, prefer `merge` over `rebase` when branch reconciliation starts stalling (for example long-running interactive/conflict loops). Resolve conflicts once, merge, and continue delivery.
6869

6970
### Small Mainline Exception

CLAUDE.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ When launching subagents with `isolation: "worktree"`, follow the protocol in `d
150150

151151
## Windows Notes
152152

153-
- If `git` resolves to Cygwin or fails with signal errors, use `C:\Program Files\Git\cmd\git.exe` explicitly.
153+
- Run `bash scripts/check-git-env.sh` to validate git resolution and index.lock state before a work session.
154+
- If `git` resolves to Cygwin or fails with signal errors, use `C:\Program Files\Git\cmd\git.exe` explicitly (or add `C:\Program Files\Git\cmd` to the front of `PATH`).
154155
- Do not chain commands with `&&` in PowerShell; use `;` and check `$LASTEXITCODE`.
155-
- If `.git/index.lock` blocks commits, check for active git processes before removing it.
156+
- If `.git/index.lock` blocks commits, check for active git processes before removing it. The `check-git-env.sh` script automates this check.

scripts/check-git-env.sh

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env bash
2+
# scripts/check-git-env.sh
3+
# Validates the local Git environment on Windows for safe agent/local workflows.
4+
# Checks:
5+
# 1. git resolves to Git for Windows (not Cygwin/MSYS)
6+
# 2. No stale .git/index.lock without an active git process
7+
#
8+
# Usage:
9+
# bash scripts/check-git-env.sh # from repo root
10+
# bash scripts/check-git-env.sh /path/to # check a specific repo
11+
12+
set -euo pipefail
13+
14+
REPO_DIR="${1:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
15+
EXIT_CODE=0
16+
17+
# ---------------------------------------------------------------------------
18+
# 1. Git executable resolution
19+
# ---------------------------------------------------------------------------
20+
GIT_PATH="$(command -v git 2>/dev/null || true)"
21+
22+
if [ -z "$GIT_PATH" ]; then
23+
echo "[ERROR] git is not on PATH. Install Git for Windows from https://git-scm.com"
24+
EXIT_CODE=1
25+
else
26+
GIT_VERSION="$(git --version 2>/dev/null || true)"
27+
echo "[INFO] git path: $GIT_PATH"
28+
echo "[INFO] git version: $GIT_VERSION"
29+
30+
# Detect Cygwin or MSYS2 (non-MinGW) git — path typically contains
31+
# /cygdrive/ or /usr/bin/. Git for Windows (MinGW) resolves to /mingw64/bin/git.
32+
case "$GIT_PATH" in
33+
/cygdrive/*|/usr/bin/git)
34+
echo "[WARN] git appears to be Cygwin or MSYS2 (non-MinGW) git ($GIT_PATH)."
35+
echo " This can cause signal errors and path translation issues."
36+
echo " Fix: add 'C:\\Program Files\\Git\\cmd' to the FRONT of your PATH,"
37+
echo " or set alias git='\"C:\\Program Files\\Git\\cmd\\git.exe\"' in your shell profile."
38+
EXIT_CODE=1
39+
;;
40+
esac
41+
42+
if echo "$GIT_VERSION" | grep -qi "cygwin"; then
43+
echo "[WARN] git --version reports Cygwin: $GIT_VERSION"
44+
echo " Use Git for Windows instead. See guidance above."
45+
EXIT_CODE=1
46+
fi
47+
48+
if [ $EXIT_CODE -eq 0 ]; then
49+
echo "[OK] git resolves to a non-Cygwin executable."
50+
fi
51+
fi
52+
53+
# ---------------------------------------------------------------------------
54+
# 2. Stale .git/index.lock detection
55+
# ---------------------------------------------------------------------------
56+
# In worktrees, .git is a file pointing to the real git dir.
57+
# Use git rev-parse to find the actual git directory.
58+
# --absolute-git-dir (Git 2.13+) returns an absolute path, avoiding the bug
59+
# where a relative ".git" would resolve against CWD instead of REPO_DIR.
60+
GIT_DIR="$(git -C "$REPO_DIR" rev-parse --absolute-git-dir 2>/dev/null || echo "$REPO_DIR/.git")"
61+
LOCK_FILE="$GIT_DIR/index.lock"
62+
63+
if [ -f "$LOCK_FILE" ]; then
64+
echo ""
65+
echo "[WARN] Stale lock file found: $LOCK_FILE"
66+
67+
# Check for active git processes (Windows: tasklist; Unix: pgrep)
68+
ACTIVE_GIT=""
69+
if command -v tasklist &>/dev/null; then
70+
ACTIVE_GIT="$(tasklist //FI "IMAGENAME eq git.exe" 2>/dev/null | grep -i "git.exe" || true)"
71+
elif command -v pgrep &>/dev/null; then
72+
ACTIVE_GIT="$(pgrep -a git 2>/dev/null || true)"
73+
fi
74+
75+
if [ -n "$ACTIVE_GIT" ]; then
76+
echo "[WARN] Active git process(es) detected — lock may be legitimate:"
77+
echo "$ACTIVE_GIT"
78+
echo " Wait for the process to finish, or kill it if stuck, then remove the lock."
79+
else
80+
echo "[WARN] No active git processes found. The lock file is likely stale."
81+
echo " Safe to remove: rm \"$LOCK_FILE\""
82+
fi
83+
EXIT_CODE=1
84+
else
85+
echo "[OK] No .git/index.lock present."
86+
fi
87+
88+
echo ""
89+
if [ $EXIT_CODE -eq 0 ]; then
90+
echo "All checks passed."
91+
else
92+
echo "One or more issues detected. See warnings above."
93+
fi
94+
95+
exit $EXIT_CODE

0 commit comments

Comments
 (0)