[BUG] Critical: git stash pop + reset --hard destroyed ~600 lines of new code and unrelated stash in worktree session

Status Open
Reported on v2.1.276
Maintainer reply None cached
Activity 0 comments · opened Sep 18, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

What happened

  • Session A (N4-4328) had uncommitted work: review.mjs (~260 lines), review.spec.mjs (~308 lines), edits to 4 files
  • Session B (N4-3927) had an uncommitted stash with ~86 files under packages/workspace/src/
  • Both sessions shared the same git repository (monorepo)
  • In Session A, bare git stash pop was issued twice, followed by git reset --hard HEAD
  • Result: Session A's N4-4328 work was destroyed, and Session B's N4-3927 stash was also destroyed

Impact

  • Primary loss: ~570 lines of new code (review.mjs, review.spec.mjs) + modifications to validate-key.mjs, validate-key.spec.mjs, key-vocabulary.json, package.json
  • Secondary loss: ~86 uncommitted files under packages/workspace/src/ belonging to N4-3927 branch
  • Recovery: 1161 unreachable commits exist in object database but are unrecoverable without manual hash identification
  • Cost: Significant token spend to faithfully re-implement from documented spec

Root causes

  1. Bare git stash pop issued despite environment forbidding it — enforcement message came too late (post-pop)
  2. git reset --hard HEAD was not blocked or confirmed when uncommitted changes were present
  3. No cross-session stash isolation — one session's mistakes destroyed another session's work
  4. Reflog was reset, eliminating recovery trail

Environment

  • Tool: Claude Code CLI
  • Session type: git worktree
  • Isolation: enabled (--worktree-path set)
  • Monorepo: shared git database across multiple concurrent worktrees/sessions

What Should Happen?

  1. Block bare git stash pop in worktree sessions before execution — not after it fails with a warning. Environment currently forbids it but enforcement arrives too late to prevent the pop.
  2. Require explicit confirmation for git reset --hard when uncommitted changes exist, with a warning about stash stack safety and cross-session risks.
  3. Tag stash entries by session ID so one session's stash pop cannot silently destroy another session's uncommitted work.
  4. Preserve reflog even after reset so git reflog can show what was discarded.

Error Messages/Logs

Steps to Reproduce

  1. Start a Claude Code session in a git worktree with uncommitted changes
  2. Issue git stash push -u -m "my-work" to stash changes from another session
  3. Push a second stash: git stash push -u -m "other-session-work" (simulates concurrent session)
  4. Issue bare git stash pop (without flags) — this pops the most recent stash
  5. If unaware of stash depth, issue git stash pop again without verifying the first pop succeeded
  6. Run git reset --hard HEAD to discard any remaining working-tree changes
  7. Run git stash list — observe: both stashes and all uncommitted work are gone
  8. Run git fsck --unreachable — observe: orphaned commits still exist in object database

Claude Model

Sonnet (default)

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.276 (Claude Code)

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

VS Code integrated terminal

Additional Information

_No response_

View original on GitHub ↗