On Fri, Apr 7, 2017 at 12:23 PM, Kevin Willford <kcwillford@xxxxxxxxx> wrote: > When using the sparse checkout feature the git reset command will add > entries to the index that will have the skip-worktree bit off but will > leave the working directory empty. File data is lost because the index > version of the files has been changed but there is nothing that is in the > working directory. This will cause the next status call to show either > deleted for files modified or deleting or nothing for files added. > The added files should be shown as untracked and modified files should > be shown as modified. > > To fix this when the reset is running if there is not a file in the > working directory and if it will be missing with the new index entry > or was not missing in the previous version, we create the previous index > version of the file in the working directory so that status will report > correctly and the files will be availble for the user to deal with. > > Signed-off-by: Kevin Willford <kewillf@xxxxxxxxxxxxx> > --- > builtin/reset.c | 34 +++++++++++++++++++++++ > t/t7114-reset-sparse-checkout.sh | 58 ++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 92 insertions(+) > create mode 100755 t/t7114-reset-sparse-checkout.sh > > diff --git a/builtin/reset.c b/builtin/reset.c > index 8ab915bfcb..8ba97999f4 100644 > --- a/builtin/reset.c > +++ b/builtin/reset.c > @@ -21,6 +21,7 @@ > #include "parse-options.h" > #include "unpack-trees.h" > #include "cache-tree.h" > +#include "dir.h" > > static const char * const git_reset_usage[] = { > N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"), > @@ -117,12 +118,45 @@ static void update_index_from_diff(struct diff_queue_struct *q, > struct diff_options *opt, void *data) > { > int i; > + int pos; You could declare this inside the for loop. > int intent_to_add = *(int *)data; > > for (i = 0; i < q->nr; i++) { > struct diff_filespec *one = q->queue[i]->one; > + struct diff_filespec *two = q->queue[i]->two; > int is_missing = !(one->mode && !is_null_oid(&one->oid)); > + int was_missing = !two->mode && is_null_oid(&two->oid); > struct cache_entry *ce; > + struct cache_entry *ceBefore; > + struct checkout state = CHECKOUT_INIT; > + > + /* > + * When using the sparse-checkout feature the cache entries that are > + * added here will not have the skip-worktree bit set. > + * Without this code there is data that is lost because the files that > + * would normally be in the working directory are not there and show as > + * deleted for the next status or in the case of added files just disappear. > + * We need to create the previous version of the files in the working > + * directory so that they will have the right content and the next > + * status call will show modified or untracked files correctly. > + */ This comment also belongs to the commit message IMHO, as it describes the bug on a high level, and when it is in the code it wastes screen real estate; commit messages however have low prices for screen real estate. ;-) > + if (core_apply_sparse_checkout && !file_exists(two->path)) > + { Coding style: Git prefers { at the end of the line: if (..) { .. > +test_expect_success 'reset after deleting file without skip-worktree bit' ' > + git checkout -f endCommit && > + git clean -xdf && > + echo "/c > +/m" >.git/info/sparse-checkout && huh? Did your mailer wrap lines here or do you intend to have a LF in the output? Assuming the latter, I think we prefer cat with here-doc for multi line content, i.e. cat >.git/info/sparse-checkout <<-\EOF /c /m EOF test_config ... ... Thanks, Stefan