fix(opencode): evict gitignored files from shadow snapshot index#24059
Closed
autopilotgrowth wants to merge 1 commit intoanomalyco:devfrom
Closed
fix(opencode): evict gitignored files from shadow snapshot index#24059autopilotgrowth wants to merge 1 commit intoanomalyco:devfrom
autopilotgrowth wants to merge 1 commit intoanomalyco:devfrom
Conversation
add() only ran check-ignore against files that were in the current source candidate set (diff-files + ls-files --others --exclude-standard). Once a file was staged and later added to .gitignore but not modified, it fell out of both candidate lists, so the existing ignore()/drop() path never saw it. It stayed in the shadow index forever, got rehashed on every write-tree, and bloated memory when sessions with large ex-untracked directories (node_modules, .android-sdk, .venv, etc.) were resumed. Union the shadow repo's cached paths into the ignore check so any file that matches current .gitignore or info/exclude is dropped regardless of whether it also appears in the source repo's candidate set. Refs anomalyco#20695 (memory megathread)
Contributor
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
Contributor
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
Contributor
|
This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window. Feel free to open a new pull request that follows our guidelines. |
This was referenced Apr 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #20695 (memory megathread — the "files staged before being added to .gitignore stay forever" case described by @thdxr).
Problem
add()only rancheck-ignoreagainst files that were in the current source candidate set (diff-files+ls-files --others --exclude-standard). Once a file was staged in the shadow repo on an early turn, then added to.gitignorebut not modified afterwards, it fell out of both candidate lists — so the existingignore()/drop()path never saw it.It stayed in the shadow index forever, got rehashed into every
write-tree, and bloated memory when sessions with large ex-untracked directories (node_modules,.android-sdk,.venv, …) were resumed.Fix
Also list the shadow repo's currently-cached paths with
git ls-files --cached, union them into theignore()check, and let the existingdrop()call evict anything that now matches. One extra git call pertrack(), negligible for sane repos, and it finally lets the user recover memory by just adding the offender to.gitignorewithout needing to wipe~/.local/share/opencode/snapshot.Verification
New test
"untracked files retroactively gitignored are evicted from shadow index"reproduces the bug:cache/big.binandcache/other.binget staged in the firsttrack(),cache/is added to.gitignore, the files are not touched, and the secondtrack()ought to drop them. I confirmed the test fails againstdevand passes with this change. It inspects the shadow tree directly viagit ls-tree -rbecausediffFull(correctly) filters gitignored paths from the user-facing diff, hiding the very rows we need to assert on.Full snapshot suite still passes (52 pass, 1 skip, 1 pre-existing
chmod-not-found failure on Windows that also fails on cleandev).