Skip to content

Conversation

@ryanwyler
Copy link
Contributor

@ryanwyler ryanwyler commented Jan 11, 2026

Summary

Fixes #7775

Fixes a bug where running opencode from a subdirectory and clicking "undo revert" would overwrite files in other directories with stale versions from weeks ago.

Problem

When running opencode from a subdirectory (e.g., project/frontend/), the unrevert operation would restore stale versions of files in other directories (e.g., project/backend/). This happened because:

  1. The snapshot index is shared across all sessions in a project
  2. git add . from a subdirectory only updates that subdirectory's entries in the index
  3. restore() used checkout-index -a which restores ALL files in the index
  4. diff() used cwd(Instance.worktree) showing diffs for unrelated directories

Solution

Scope both restore() and diff() to Instance.directory:

  • restore() now lists files under the session directory prefix using ls-tree and only restores those specific files
  • diff() now uses cwd(Instance.directory) so the -- . path spec is relative to the session directory

Steps to Reproduce

  1. Create a project with multiple subdirectories:
mkdir -p /tmp/testproject/frontend /tmp/testproject/backend
cd /tmp/testproject
git init && git config user.email "test@test.com" && git config user.name "Test"
echo 'console.log("frontend")' > frontend/app.ts
echo 'println("backend ORIGINAL")' > backend/server.go
git add . && git commit -m "Initial"
  1. Run opencode from backend/, make a change, then exit:
cd /tmp/testproject/backend
opencode
# Ask it to modify server.go, then exit
  1. Update backend externally (simulates multitasking with different agents or personally making edits outside of opencode):
echo 'println("backend CURRENT")' > backend/server.go
git add . && git commit -m "Update backend"
  1. Run opencode from frontend/, make a change, revert, then unrevert:
cd /tmp/testproject/frontend
opencode
# Ask it to modify app.ts
# Click "Revert" on the assistant's message
# Click "Undo Revert"
  1. Check if backend was corrupted:
cat /tmp/testproject/backend/server.go
# BUG: Shows "backend ORIGINAL" (stale version)
# FIXED: Shows "backend CURRENT" (unchanged)

Testing

  • All existing snapshot tests pass
  • Manually verified the fix prevents stale file restoration
  • Verified revert/unrevert still works correctly for files in the session directory

Bug History

Traced the origin of this bug through git history:

Date Commit Change Impact
Jul 1, 2025 11d042be2 Original snapshot implementation using isomorphic-git with per-session snapshots Safe - each session isolated
Jul 24, 2025 284c01018 Refactored to shell git commands with checkout-index -a -f Bug introduced - restores ALL files in index
Sep 1, 2025 f993541e0 Changed from per-session to per-project snapshots Bug became severe - sessions now share snapshot index

The original per-session implementation was safe because each session had its own isolated snapshot directory. The bug was introduced when refactoring to shell git commands (checkout-index -a restores all files regardless of cwd), and became a real problem when snapshots became shared per-project (stale entries from other sessions persist in the shared index).

When running opencode from a subdirectory, the snapshot system would
restore stale files from other directories during unrevert. This happened
because:

1. The snapshot index is shared across all sessions in a project
2. git add . from a subdirectory only updates that subdirectory's entries
3. restore() used checkout-index -a which restores ALL files in the index
4. diff() used cwd(Instance.worktree) showing diffs for unrelated directories

Fix by scoping both restore() and diff() to Instance.directory:
- restore() now lists files under the session directory prefix and only
  restores those specific files
- diff() now uses cwd(Instance.directory) so the path spec is relative
  to the session directory
@github-actions
Copy link
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions
Copy link
Contributor

The following comment was made by an LLM, it may be inaccurate:

No duplicate PRs found

@ryanwyler ryanwyler changed the title fix(snapshot): scope restore and diff to session directory fix(snapshot): reverting in a session running in a nested directory can wipe out other files that have changed Jan 11, 2026
@ryanwyler ryanwyler changed the title fix(snapshot): reverting in a session running in a nested directory can wipe out other files that have changed fix(snapshot): reverting in a session can wipe out other files that have changed Jan 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unrevert from subdirectory overwrites files in other directories with stale versions

1 participant