anthropics / anthropics/claude-code

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

Open
#95,355 0 comments 0 reactions 0 assignees View on GitHub
area:bash bug data-loss has repro platform:macos platform:vscode
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

### Preflight Checklist

- [x] I have searched [existing issues](https://github.com/anthropics/claude-code/issues?q=is%3Aissue%20state%3Aopen%20label%3Abug) 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

```shell

```

### 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_

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the Claude Code CLI handling of git worktree sessions and the command paths for bare git stash pop and git reset --hard. Reproduce the two-session sequence in the issue, then trace when warnings or confirmations are applied. Done should prevent the reported cross-session loss and preserve a verifiable recovery path, with tests covering concurrent stashes and destructive resets.

Written by the indexing model from the issue text.

Assessment

Tech stack
git
Domain
cli, tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.