Skip to content

Fix reset --mixed skipping hydrated files due to skip-worktree#2016

Closed
tyrielv wants to merge 2 commits into
microsoft:masterfrom
tyrielv:tyrielv/fix-reset-mixed-skipworktree
Closed

Fix reset --mixed skipping hydrated files due to skip-worktree#2016
tyrielv wants to merge 2 commits into
microsoft:masterfrom
tyrielv:tyrielv/fix-reset-mixed-skipworktree

Conversation

@tyrielv

@tyrielv tyrielv commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Problem

After git reset --mixed HEAD~N, hydrated files (read via blame/cat-file but not modified) retain skip-worktree because they are not in ModifiedPaths. Git skips the working-tree vs index comparison for these files, so status reports clean when the on-disk content doesn't match the new index entry.

Manually confirmed: control repo outputs 224 modified files including M Readme.md; GVFS repo outputs 223 — Readme.md missing from reset output and status.

Fix

Adds a PrepareForReset pre-command hook (mirroring the existing PrepareForUnstage pattern for estore --staged):

  1. ResetCommandParser — detects mixed resets, extracts target commit
  2. Program.Reset → IPC → InProcessMountFileSystemCallbacks.AddResetDiffToModifiedPaths — runs git diff-tree HEAD <target>, adds changed paths to ModifiedPaths
  3. Skip-worktree cleared for affected files → git correctly reports them

Testing

  • Repro test (ReproResetMixedSkipWorktree): hydrates Readme.md via blame, then resets to HEAD~1 where it changed. Expected to fail without the fix (pushed as first commit to verify CI catches it).
  • Unit tests: 12 tests for ResetCommandParser arg parsing
  • All 830 existing unit tests pass

Commits

  1. ⬅️ Test only (current push) — should FAIL in CI, proving the repro test catches the bug
  2. Fix — will be pushed after CI confirms failure

tyrielv added 2 commits June 10, 2026 15:49
Adds ReproResetMixedSkipWorktree to CorruptionReproTests. The test
hydrates Readme.md via blame (materializes on disk but not in
ModifiedPaths, so skip-worktree stays set), then runs reset HEAD~1.

On the FunctionalTests/20201014 branch, Readme.md is the only file
that differs between HEAD and HEAD~1. The control repo correctly
reports it as modified after the reset; the GVFS repo does not because
skip-worktree hides the working-tree vs index mismatch.

This test is expected to FAIL until the fix is applied.

Assisted-by: Claude Opus 4.6
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Adds PrepareForReset pre-command hook (mirroring PrepareForUnstage)
that diffs HEAD against the target commit and adds changed files to
ModifiedPaths before the reset runs. This ensures skip-worktree is
cleared for hydrated files so git correctly reports them as modified.

Components:
- ResetCommandParser: detects mixed resets, extracts target commit
- Program.Reset: sends PrepareForReset IPC to mount process
- FileSystemCallbacks.AddResetDiffToModifiedPaths: runs git diff-tree,
  adds changed paths to ModifiedPaths
- InProcessMount: handles PrepareForReset messages
- ResetCommandParserTests: 12 unit tests for arg parsing

Assisted-by: Claude Opus 4.6
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
@tyrielv tyrielv marked this pull request as ready for review June 10, 2026 23:28
{
// Output is null-separated paths. The first entry from diff-tree is
// the target commit SHA (when given a commit, not a tree), skip it.
string[] parts = result.Output.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splitting the diff-tree -z output can leave a stray newline element that gets added to ModifiedPaths.

@tyrielv

tyrielv commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

More investigation is suggesting this needs to be fixed in git.exe, which makes a wrong assumption that placeholder files don't exist on disk (but they do if they've had contents read)

@tyrielv tyrielv closed this Jun 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.

2 participants