It's a very unexpected behaviour when a user sees a deleted file after a merge 
with enabled sparse-checkout. Moreover, when the user resolves merge conflicts 
and commits the changes with the command "git commit -am xxx", a repository can 
be broken because all the moved files will be deleted. Finally, it's really 
hard to find a user who deleted these files because "git log file" doesn't show 
any merge commits by default. I'm not sure that my fix is correct but I checked 
all tests and I didn't find a better way to prevent files deleting.
---
 merge-recursive.c                    |  9 +++++---
 t/t6042-merge-rename-corner-cases.sh | 41 ++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index e349126..25dc701 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1724,9 +1724,12 @@ static int merge_content(struct merge_options *o,
                 */
                path_renamed_outside_HEAD = !path2 || !strcmp(path, path2);
                if (!path_renamed_outside_HEAD) {
-                       add_cacheinfo(o, mfi.mode, &mfi.oid, path,
-                                     0, (!o->call_depth), 0);
-                       return mfi.clean;
+                       struct stat st;
+                       if (lstat(path, &st) == 0) {
+                               add_cacheinfo(o, mfi.mode, &mfi.oid, path,
+                                             0, (!o->call_depth), 0);
+                               return mfi.clean;
+                       }
                }
        } else
                output(o, 2, _("Auto-merging %s"), path);
diff --git a/t/t6042-merge-rename-corner-cases.sh 
b/t/t6042-merge-rename-corner-cases.sh
index 411550d..5d84418 100755
--- a/t/t6042-merge-rename-corner-cases.sh
+++ b/t/t6042-merge-rename-corner-cases.sh
@@ -575,4 +575,45 @@ test_expect_success 'rename/rename/add-dest merge still 
knows about conflicting
        test ! -f c
 '
 
+test_expect_success 'move file/sparse-checkout/merge should not delete moved 
file' '
+       git rm -rf . &&
+       git clean -fdqx &&
+       rm -rf .git &&
+       git init &&
+
+       echo output >.gitignore &&
+       echo .gitignore >>.gitignore &&
+
+       echo b1 >b1 &&
+       git add b1 &&
+       git commit -m b1 &&
+
+       mkdir excluded &&
+       echo problem >excluded/to-be-moved.txt &&
+       git add excluded/to-be-moved.txt &&
+       git commit -m to-be-moved &&
+       git tag split_point &&
+
+       echo b2 >b2 &&
+       git add b2 &&
+       git commit -m b2 &&
+       git tag b2 &&
+
+       git reset --hard split_point &&
+
+       git mv excluded/to-be-moved.txt excluded/moved.txt &&
+       git commit -m move &&
+       git tag b1 &&
+
+       git config core.sparsecheckout true &&
+       echo "/*" >.git/info/sparse-checkout &&
+       echo "!excluded/" >>.git/info/sparse-checkout &&
+       git read-tree -mu HEAD &&
+
+       git merge -m merge b2 &&
+
+       git status >output &&
+       test_i18ngrep "nothing to commit" output
+'
+
 test_done
-- 
2.7.4 (Apple Git-66)

Reply via email to