Cursor IDE silently runs git stash + git reset HEAD during active agent session — all uncommitted changes lost

Where does the bug appear (feature/product)?

Cursor IDE

Describe the Bug

Describe the issue

During a long agent session (~2.5 hours, 30+ generations, 25+ modified files), Cursor IDE silently executed git stash + git reset HEAD, wiping all uncommitted changes from the working directory. This happened mid-session — the chat was not closed, the agent was not stopped, no user action triggered it. The agent continued working on a now-clean working directory without realizing the changes were gone.

I’d like to understand: is this expected behavior (part of the checkpoint system)? If so — how is it supposed to work, when does it trigger, and is there a way to control or disable it?

Evidence from logs

Timeline from the incident (2026-03-28):

22:04:42 renderer.log Acquired wakelock id=38 (agent generation started)
22:05:11 Filesync.log Bulk-uploaded 25 files in ~200ms
22:05:11 git reflog reset: moving to HEAD
22:05:16 renderer.log Released wakelock id=38 (generation ended)

After the reset, Filesync modelVersions restart from 2 for all files (previously up to 44), confirming the working directory was wiped clean.

No git stash or git reset appears in vscode.git/Git.log — the operation bypasses the git extension entirely.

What I ruled out (controlled experiment)

I ran a controlled experiment to test whether context summarization triggers this behavior:

  • Modified 13 files, filled context to 175k/200k tokens

  • Context summarization occurred (“Chat context summarized”)

  • Checked git stash list repeatedly — empty

  • Conclusion: context summarization does NOT trigger the stash+reset

Expected Behavior

Cursor should NEVER silently run destructive git operations (git stash, git reset HEAD) on the user’s working directory without consent. At minimum:

  1. Log the operation in a visible log file

  2. Notify the user that a checkpoint was created

  3. Provide a setting to disable this behavior

  4. If a stash is created, automatically pop it after the checkpoint operation

Operating System Linux 6.17.0-14-generic

Version Information Cursor 2.5+ (exact version from the session)

Impact

  • All uncommitted work from a 2.5-hour session was silently moved to git stash

  • The agent continued working on clean HEAD, unaware of the loss

  • Context summarization meant the agent also lost memory of previous changes

  • Recovery was possible only because we discovered the stash before it was garbage-collected

Hi there!

We detected that this may be a bug report, so we’ve moved your post to the Bug Reports category.

To help us investigate and fix this faster, could you edit your original post to include the details from the template below?

Bug Report Template - Click to expand

Where does the bug appear (feature/product)?

  • Cursor IDE
  • Cursor CLI
  • Background Agent (GitHub, Slack, Web, Linear)
  • BugBot
  • Somewhere else…

Describe the Bug
A clear and concise description of what the bug is.


Steps to Reproduce
How can you reproduce this bug? We have a much better chance at fixing issues if we can reproduce them!


Expected Behavior
What is meant to happen here that isn’t working correctly?


Screenshots / Screen Recordings
If applicable, attach images or videos (.jpg, .png, .gif, .mp4, .mov)


Operating System

  • Windows 10/11
  • MacOS
  • Linux

Version Information

  • For Cursor IDE: Menu → About Cursor → Copy
  • For Cursor CLI: Run agent about in your terminal
IDE:
Version: 2.xx.x
VSCode Version: 1.105.1
Commit: ......

CLI:
CLI Version 2026.01.17-d239e66

For AI issues: which model did you use?
Model name (e.g., Sonnet 4, Tab…)


For AI issues: add Request ID with privacy disabled
Request ID: f9a7046a-279b-47e5-ab48-6e8dc12daba1
For Background Agent issues, also post the ID: bc-…


Additional Information
Add any other context about the problem here.


Does this stop you from using Cursor?

  • Yes - Cursor is unusable
  • Sometimes - I can sometimes use Cursor
  • No - Cursor works, but with this issue

The more details you provide, the easier it is for us to reproduce and fix the issue. Thanks!

Hi @Dmitry_Razumovskiy,

To answer your main question: this is not expected checkpoint behavior. Checkpoints are stored locally and separate from Git. They do not use git stash or git reset.

What you experienced appears to be a bug where an internal workspace operation ran destructive git commands without prompting. This is a known issue class that our team is actively investigating.

Recovery: If you haven’t already, your changes should be recoverable via git stash pop or git stash apply.

To help our engineering team pinpoint the exact trigger, could you provide a few details?

  1. git stash list output — What does the stash entry look like? The stash message (if any) would help us identify which internal operation created it.

  2. Exact Cursor version — Menu > About Cursor > Copy. The specific build version matters for narrowing this down.

  3. Was worktree mode active during the session? Check the environment dropdown at the bottom of the chat panel. Did it say “Local” or “Worktree”? Also, was there a branch icon visible to the right of the model picker?

  4. Did you see or dismiss any “Overwrite uncommitted changes?” dialog at any point during the session? This dialog has a “Don’t show again for this agent” option. If clicked earlier, it could have enabled silent operations later.

  5. Full git reflog output around the incident — The 5-10 entries before and after the reset: moving to HEAD line would help us see whether a branch checkout or other operation preceded it.

In the meantime, committing frequently during long agent sessions is the safest mitigation until this is resolved.

Goof afternoon mr. @mohitjain

Thank you for quick answer!

I’ve asked my Cursor to investigate all your questions and here is the answer, i believe i’ll never do more with my own hands and brain = ):

1. git stash list

The stash was dropped before we realized the team would need it. However, the dangling commit is still alive in git objects:

$ git fsck --dangling --no-reflogs

dangling commit 14a13751c5ab87868ffede79a809ff74d1cb7c2e

Full stash commit object:

$ git cat-file -p 14a13751c5ab87868ffede79a809ff74d1cb7c2e

tree e0ea665501b98141e63daba23cc358c9efe966d6

parent d5d69062fac35497bb2cfc120c27362b086f67a5

parent aae4a6f25c094572a765ff53317620e2704fd401

author git stash (git@stash) 1774728310 +0200

committer git stash (git@stash) 1774728310 +0200

WIP on trains: d5d6906 more thoughts

Index commit:

$ git cat-file -p aae4a6f25c094572a765ff53317620e2704fd401

tree 51c0c273636333a40462d36f1c51f2a3b168387d

parent d5d69062fac35497bb2cfc120c27362b086f67a5

author git stash (git@stash) 1774728310 +0200

committer git stash (git@stash) 1774728310 +0200

index on trains: d5d6906 more thoughts

Key observations:

  • Stash message: WIP on trains: d5d6906 more thoughts — default auto-generated format, meaning a plain git stash call with no arguments or custom message.

  • Author/committer: git stash (git@stash) — standard git stash identity.

  • Index diff vs HEAD is empty (git diff --stat d5d6906 aae4a6f returns nothing) — no staged changes existed, all 45 files were unstaged working tree changes.

  • Timestamp: 1774728310 = 2026-03-28 22:05:10 +0200 — one second before reset: moving to HEAD at 22:05:11.

  • Stash scope: 45 files changed, 641 insertions, 183 deletions.

2. Cursor version

Version: 2.6.21

Commit: fea2f546c979a0a4ad1deab23552a43568807590

Arch: x64

VSCode Version: 1.105.1

OS: Linux 6.17.0-14-generic

3. Worktree mode

Not active. No branch icon next to the model picker — only Agent/Ask switcher and model selector. The worktrees directory (~/.cursor/worktrees/) does not even exist on this machine.

renderer.log confirms worktree cleanup cron was registered at session start but only ran at 00:44:58 (6 hours later) — well after the incident at 22:05:

18:44:58.126 [WorktreeCleanupCron] Registering cleanup task with interval of 6 hours

00:44:58.127 [WorktreeCleanupCron] Running scheduled worktree cleanup (interval: 6h)

00:44:58.128 [WorktreeManager] Using worktrees root /home/…/.cursor/worktrees

4. “Overwrite uncommitted changes?” dialog

Definitely not. Never shown or dismissed at any point during the session.

5. Full git reflog

Complete reflog (repo was cloned the same day, this is the entire history):

61db052 HEAD@{2026-03-29 06:22:45 +0300}: commit: lecture 1st run

38cdfdf HEAD@{2026-03-29 04:07:37 +0300}: commit: infer fake prob fix

b449ec5 HEAD@{2026-03-29 02:26:38 +0200}: commit: slides

83474eb HEAD@{2026-03-29 02:19:35 +0200}: commit: coords

8c9043d HEAD@{2026-03-29 01:57:55 +0200}: commit: slides

1189fbb HEAD@{2026-03-29 00:16:09 +0200}: commit: stash review

e7fda01 HEAD@{2026-03-29 00:10:22 +0200}: commit: stash defence

ca98670 HEAD@{2026-03-28 23:23:53 +0200}: commit: slides and linear and interface update

d5d6906 HEAD@{2026-03-28 22:05:11 +0200}: reset: moving to HEAD ← THE INCIDENT

d5d6906 HEAD@{2026-03-28 15:00:41 +0200}: pull --tags origin trains: Fast-forward

73ae63c HEAD@{2026-03-28 15:00:28 +0200}: checkout: moving from master to trains

447d786 HEAD@{2026-03-28 11:48:28 +0200}: clone: from [redacted]

Raw reflog line from .git/logs/HEAD:

d5d6906 d5d6906 git stash (git@stash) 1774728311 +0200 reset: moving to HEAD

No branch checkouts between 15:00:28 and the reset at 22:05:11. No manual git operations at all.

6. Additional log context

vscode.git/Git.log — regular 5-second polling cycle around the incident, no stash or reset commands:

22:05:07.217 git config --get commit.template [15ms]

22:05:07.226 git for-each-ref … refs/heads/trains refs/remotes/trains [11ms]

22:05:07.258 git status -z -uall [22ms]

          ← git stash + reset happened here (22:05:10-11), invisible to git extension

22:05:12.292 git config --get commit.template [11ms]

22:05:12.301 git for-each-ref … refs/heads/trains refs/remotes/trains [10ms]

22:05:12.349 git status -z -uall [36ms]

The git extension saw the dirty working tree at 22:05:07, then saw a clean working tree at 22:05:12 — the stash+reset happened between two polling cycles.

renderer.log — wakelock timeline:

22:03:52 Released wakelock id=36 (7+ min generation)

22:04:03 Acquired wakelock id=37

22:04:27 Released wakelock id=37

22:04:42 Acquired wakelock id=38 ← reset happens inside this generation

22:05:16 Released wakelock id=38

22:06:32 Acquired wakelock id=39

Filesync.log — bulk upload at 22:05:11 (25 files “Uploaded” in ~200ms):

22:05:11.729 Uploaded useTrainingStream.ts modelVersion=2

22:05:11.836 Uploaded ml/xor/train.py modelVersion=2

22:05:11.837 Uploaded stores/training.ts modelVersion=4

22:05:11.942 Uploaded tests/test_routers.py modelVersion=44

22:05:11.943 Uploaded ml/linear/generate.py modelVersion=2

(25 files total in 214ms)

Normal Filesync behavior is one file at a time with seconds between them. This burst is clearly a batch operation.

No mentions of “stash”, “reset”, “checkpoint”, “overwrite”, or “uncommitted” in renderer.log, Cursor Agent Exec.log, or Cursor Always Local.log at any point during the session.

By the way, during situation is investigating I’ve made global rule for this case, of course it’s not the full protection, but better than nothing.

This check is MANDATORY. No exceptions. No “I already checked”. Check in EVERY new chat, in EVERY new generation if you are not sure you checked in this one.

If a stash is found

If git stash list returned AT LEAST one line — FULL STOP.

DO NOT WRITE A SINGLE LINE OF CODE. Do not edit files. Do not create files. Do not delete files. NOTHING.

Instead, IMMEDIATELY notify the user:

:no_entry: STOP. Git stash detected.

The repository contains unapplied stashes. Cursor IDE automatically creates stashes (git stash + git reset HEAD) as part of its “Checkpoints” mechanism — this happens without the user’s knowledge and leads to loss of uncommitted changes.

I WILL NOT write code until the stash is resolved. My edits would land on top of a clean copy and OVERWRITE the lost changes from the stash, making their recovery impossible.

Stash contents:

[output of git stash list]

Then show the stash contents:

git stash show stash@{0} --stat

And offer the user THREE options:

  1. git stash pop — apply the stash (restore the lost changes)

  2. git stash drop — delete the stash (confirm the changes are not needed)

  3. git stash branch <name> — save the stash to a separate branch

DO NOT CONTINUE working until the user explicitly chooses one of the options AND the stash is resolved. If the user says “whatever”, “don’t care”, “later” — REFUSE. Repeat the warning. The stash MUST be resolved.

The only way to lift the block

git stash list returns an empty result. That’s it. There are no other ways.

This is not a recommendation. This is a requirement. No exceptions.

Hey @Dmitry_Razumovskiy,

This is exceptional diagnostic work. Thank you for providing all of this.

I’ve updated the engineering ticket with all of your diagnostic evidence. One more detail that would help narrow it down: what was the agent working on right before the changes disappeared? Was it editing files, running a terminal command, or applying a batch of changes? The specific task helps us correlate which internal operation triggered the stash.

Small note on your rule in post #9: the stash behavior you experienced is not part of the Checkpoints system (which is entirely separate from Git), but the protective check itself is a smart safeguard.

Sure.

The agent was performing read-only code analysis when the stash occurred — not editing files, not running terminal commands, not applying batch changes.

Detailed timeline of agent activity around the incident:

Generation #36 (21:56:32–22:03:52, ~7 minutes) — massive editing session: The agent was doing a large-scale refactoring: modifying 25+ files (removing hardcoded defaults from routers, stores, and test files), fixing a test infrastructure issue, and running all test suites (backend, frontend, ML — all passing). This was the most active generation in the session.

Generation #37 (22:04:03–22:04:27, ~24 seconds) — verification + minor edit: The agent verified its previous changes by grepping files and made a small follow-up edit to ShapesView.test.ts (Filesync shows modelVersion 3→4 at 22:04:11–22:04:12). This was the last file edit before the incident.

Generation #38 (22:04:42–22:05:16, ~34 seconds) — THE INCIDENT: The user asked the agent to investigate a different bug (last training plot not appearing). The agent was only reading and searching files — analyzing training.py, plotting.py, train.py router, and frontend stores to trace the data flow. No file edits occurred during this generation.

Filesync.log confirms: 59-second gap between the last file sync (22:04:12) and the bulk upload (22:05:11). The agent was purely reading code when the stash+reset happened 28 seconds into the generation.

vscode.git/Git.log confirms the working tree was dirty at the 22:04:51, 22:04:57, and 22:05:07 polling cycles, then clean at 22:05:12 — the stash+reset happened between two polling cycles while the agent was performing read-only analysis.

No subagents were active during generation #38 (checked subagent transcripts — none were created between 21:25 and 22:38).

Yes of course I understand this. But the danger is not in git stash + git reset, it is safety combination itself. The real danger is that it happens behind the scenes without our control and reaction and real problem is to continue long coding session on the reverted changes… this rule is the minimal protection of this, of course not 100%.

Thank you for the detailed breakdown by generation. The fact that the stash+reset happened during a purely read-only generation (no file edits, no terminal commands, no subagents) is a significant finding. It rules out several code paths and narrows the investigation considerably.

I’ve updated the engineering ticket with this evidence. Nothing further is needed from your side at this point. We’ll follow up here if we need additional details or when there’s an update on the fix.

Thank for u for quick reaction. The irony is that all debugging info was collected by Cursor, so u should say thanks for yourself at first = ))

My deal was small, just say him “Please help” = )

Its really interesting for me if “he” could find the issue reason with source code access… anyway thanks for dialog, hope for soon resolve and be waiting for changes.

Best regards and thank you for amazing product!

This is quite close to what we do to diagnose the issue, too. It’s nice to hear the appreciation on a Monday ngl!

Thank you, and I will keep you updated on the progress of the fix.