microsoft/VFSForGit

'gvfs sparse' overwrites users's changes if it needs to call dehydrate

wilbaker opened this issue · 0 comments

Related to the changes in #1601

If a user has dirty files inside the sparse set and then performs a --prune that needs to remove folder(s) the dirty files will lose their changes.

Example:

In this example test.txt loses its changes:

F:\testSparse\test\src>gvfs sparse --set ace --prune
Running git status...Succeeded
Updating sparse folder set...Succeeded
No folders to update in sparse set.
Finding folders to prune...Succeeded
Found 0 folders to prune.

F:\testSparse\test\src>mkdir new

F:\testSparse\test\src>echo foo >> ace\test.txt

F:\testSparse\test\src>git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   ace/test.txt

no changes added to commit (use "git add" and/or "git commit -a")

F:\testSparse\test\src>gvfs sparse --set ace --prune
Running git status...Succeeded
Updating sparse folder set...Succeeded
No folders to update in sparse set.
Finding folders to prune...Succeeded
Found 1 folders to prune.

WARNING: If you abort the sparse after this point, the repo may become corrupt

Unmounting...Succeeded
Cleaning up folders...Succeeded
Mounting...Succeeded
new folder prune successful.

F:\testSparse\test\src>git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Root Cause

As part of dehydrating folders the dehydrate verb sends a message to the mount process. In its handling of that message the mount process ends up calling git checkout -f HEAD and that causes the files to be overwritten:

gitProcess.ForceCheckout(GVFSConstants.DotGit.HeadName);

We should probably update this code to only perform the checkout -f against the folders that were dehydrated.