Problem
When committing across multiple git worktrees in parallel (e.g., 5 parallel git commit calls in separate worktrees), pre-commit hooks' git stash push/git stash pop operations corrupt branch state because git stash is shared across all worktrees.
What happened (session 2026-03-14)
5 worktrees were created from origin/Dev_new_gui for issues #1667, #1663, #1571, #1564, #1517. All 5 commits were launched in parallel. Result:
Root cause
Git worktrees share the same .git/objects, .git/refs, and critically, .git/refs/stash. Pre-commit hooks call git stash push --include-untracked before validation and git stash pop after. When multiple worktrees run pre-commit hooks simultaneously:
- Worktree A stashes its changes
- Worktree B stashes its changes (pushing A's stash down)
- Worktree A pops — gets B's stash instead of its own
- Changes leak across branches
Why branch guard (#1670) didn't help
The branch guard hook checks if the current branch name changed between pre-commit and commit time. In this case, the branch names didn't change — the stash contamination caused commits to include wrong content but on the "right" branch. The commits were then pushed to remote branches that happened to be fast-forwardable into Dev_new_gui.
Impact
Critical — Commits bypass PR review process and land directly on the integration branch. This defeats code review, CI gating, and change tracking.
Mitigation (immediate)
Added to MEMORY.md and CLAUDE.md:
NEVER commit worktrees in parallel. Always commit sequentially.
Proposed fix
- Lock file per worktree: Pre-commit hook acquires a repo-wide lock (
flock /path/to/.git/pre-commit.lock) before stashing, ensuring only one worktree runs pre-commit at a time
- Disable stash in hooks: Configure pre-commit to skip stash (
--no-stash flag) — requires all files to be staged before commit (already enforced by policy)
- Worktree-scoped stash: Git doesn't natively support this, but a wrapper script could use per-worktree temp branches instead of stash
Discovered during
Team-implement session fixing #1667, #1663, #1564, #1571, #1517
Related issues
Problem
When committing across multiple git worktrees in parallel (e.g., 5 parallel
git commitcalls in separate worktrees), pre-commit hooks'git stash push/git stash popoperations corrupt branch state because git stash is shared across all worktrees.What happened (session 2026-03-14)
5 worktrees were created from
origin/Dev_new_guifor issues #1667, #1663, #1571, #1564, #1517. All 5 commits were launched in parallel. Result:Dev_new_guiinstead of their feature branchesd67adbd05(Bug: getSeverityColor() exported but has zero callers — dead code in useCssVars.ts #1667),02b1f1846(Bug: .gitignore core.* pattern blocks legitimate files in subdirectories #1663),d807d440f(fix: bug_predictor.py line 1202 exceeds 100-char line length limit (E501) #1564) appeared inorigin/Dev_new_guihistory without PRsRoot cause
Git worktrees share the same
.git/objects,.git/refs, and critically,.git/refs/stash. Pre-commit hooks callgit stash push --include-untrackedbefore validation andgit stash popafter. When multiple worktrees run pre-commit hooks simultaneously:Why branch guard (#1670) didn't help
The branch guard hook checks if the current branch name changed between pre-commit and commit time. In this case, the branch names didn't change — the stash contamination caused commits to include wrong content but on the "right" branch. The commits were then pushed to remote branches that happened to be fast-forwardable into Dev_new_gui.
Impact
Critical — Commits bypass PR review process and land directly on the integration branch. This defeats code review, CI gating, and change tracking.
Mitigation (immediate)
Added to MEMORY.md and CLAUDE.md:
Proposed fix
flock /path/to/.git/pre-commit.lock) before stashing, ensuring only one worktree runs pre-commit at a time--no-stashflag) — requires all files to be staged before commit (already enforced by policy)Discovered during
Team-implement session fixing #1667, #1663, #1564, #1571, #1517
Related issues