git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 1/7] reset: behave correctly with sparse-checkout

From
Elijah Newren <newren@gmail.com>
Date
Oct 6, 2021, 01:46 UTC
Message-ID
<CABPp-BFFG=puwpB4Gz8nWU=CNMUrLbH7XPTkpSGqWedTK2NWLg@mail.gmail.com>
In-Reply-To
<22c69bc60308fef13acd7c3aab4e11e175c89440.1633440057.git.gitgitgadget@gmail.com>
Hi!

It appears Junio has already commented on this patch and in more detail, but since I already typed up some comments I'll send them along in case they are useful.

On Tue, Oct 5, 2021 at 6:20 AM Kevin Willford via GitGitGadget <gitgitgadget@gmail.com> wrote:

Show 6 quoted lines
>
> From: Kevin Willford <kewillf@microsoft.com>
>
> When using the sparse checkout feature, 'git reset' will add entries to
> the index that will have the skip-worktree bit off but will leave the
> working directory empty.
Yes, that seems like a problem.
Show 6 quoted lines
> 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 'git 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.

Why is the solution to add the files to the working tree rather than to make sure the files have the skip-worktree bit set? That's not at all what I would have expected.

Show 5 quoted lines
> 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.
s/availble/available/
Show 36 quoted lines
>
> This fixes a documented failure from t1092 that was created in 19a0acc
> (t1092: test interesting sparse-checkout scenarios, 2021-01-23).
>
> Signed-off-by: Kevin Willford <kewillf@microsoft.com>
> Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
> Signed-off-by: Victoria Dye <vdye@github.com>
> ---
>  builtin/reset.c                          | 24 ++++++++--
>  t/t1092-sparse-checkout-compatibility.sh |  4 +-
>  t/t7114-reset-sparse-checkout.sh         | 61 ++++++++++++++++++++++++
>  3 files changed, 83 insertions(+), 6 deletions(-)
>  create mode 100755 t/t7114-reset-sparse-checkout.sh
>
> diff --git a/builtin/reset.c b/builtin/reset.c
> index 51c9e2f43ff..3b75d3b2f20 100644
> --- a/builtin/reset.c
> +++ b/builtin/reset.c
> @@ -25,6 +25,8 @@
>  #include "cache-tree.h"
>  #include "submodule.h"
>  #include "submodule-config.h"
> +#include "dir.h"
> +#include "entry.h"
>
>  #define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
>
> @@ -130,11 +132,27 @@ static void update_index_from_diff(struct diff_queue_struct *q,
>         int intent_to_add = *(int *)data;
>
>         for (i = 0; i < q->nr; i++) {
> +               int pos;
>                 struct diff_filespec *one = q->queue[i]->one;
> -               int is_missing = !(one->mode && !is_null_oid(&one->oid));
> +               struct diff_filespec *two = q->queue[i]->two;
> +               int is_in_reset_tree = one->mode && !is_null_oid(&one->oid);

Isn't !is_null_oid(&one->oid) redundant to checking one->mode? When does the diff machinery ever give you a non-zero mode with a null oid?

Also, is_in_reset_tree == !is_missing; I'll note that below.
Show 5 quoted lines
>                 struct cache_entry *ce;
>
> +               /*
> +                * If the file being reset has `skip-worktree` enabled, we need
> +                * to check it out to prevent the file from being hard reset.

I don't understand this comment. If the file wasn't originally in the index (is_missing), and is being added to it, and is correctly marked as skip_worktree, and the file isn't in the working tree, then it sounds like everything is already in a good state. Files outside the sparse checkout are meant to have the skip_worktree bit set and be missing from the working tree.

Also, I don't know what you mean by 'hard reset' here.
Show 9 quoted lines
> +                */
> +               pos = cache_name_pos(two->path, strlen(two->path));
> +               if (pos >= 0 && ce_skip_worktree(active_cache[pos])) {
> +                       struct checkout state = CHECKOUT_INIT;
> +                       state.force = 1;
> +                       state.refresh_cache = 1;
> +                       state.istate = &the_index;
> +
> +                       checkout_entry(active_cache[pos], &state, NULL, NULL);

Does this introduce an error in the opposite direction from the one stated in the commit message? Namely we have two things that should be in sync: the skip_worktree flag stating whether the file should be present in the working directory (skip_worktree), and the question of whether the file is actually in the working directory. In the commit message, you pointed out a case where the y were out of sync one way: the skip_worktree flag was not set but the file was missing. Here you say the skip_worktree flag is set, but you add it to the working tree anyway.

Or am I misunderstanding the code?
> +               }
> +

[I did some slight editing to the diff to make the next two parts appear next to each other]

> -               if (is_missing && !intent_to_add) {
> +               if (!is_in_reset_tree && !intent_to_add) {

I thought this was some subtle bugfix or something, and spent a while trying to figure it out, before realizing that is_in_reset_tree was simply defined as !is_missing (for some reason I was assuming it was dealing with two->mode while is_missing was looking at one->mode). So this is a simple variable renaming, which I think is probably good, but I'd prefer if this was separated into a different patch to make it easier to review.

Show 9 quoted lines
>                         remove_file_from_cache(one->path);
>                         continue;
>                 }
> @@ -144,7 +162,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,
>                 if (!ce)
>                         die(_("make_cache_entry failed for path '%s'"),
>                             one->path);
> -               if (is_missing) {
> +               if (!is_in_reset_tree) {
same note as above; the variable rename is good, but should be a separate patch.
Show 88 quoted lines
>                         ce->ce_flags |= CE_INTENT_TO_ADD;
>                         set_object_name_for_intent_to_add_entry(ce);
>                 }
> diff --git a/t/t1092-sparse-checkout-compatibility.sh b/t/t1092-sparse-checkout-compatibility.sh
> index 886e78715fe..c5977152661 100755
> --- a/t/t1092-sparse-checkout-compatibility.sh
> +++ b/t/t1092-sparse-checkout-compatibility.sh
> @@ -459,9 +459,7 @@ test_expect_failure 'blame with pathspec outside sparse definition' '
>         test_all_match git blame deep/deeper2/deepest/a
>  '
>
> -# NEEDSWORK: a sparse-checkout behaves differently from a full checkout
> -# in this scenario, but it shouldn't.
> -test_expect_failure 'checkout and reset (mixed)' '
> +test_expect_success 'checkout and reset (mixed)' '
>         init_repos &&
>
>         test_all_match git checkout -b reset-test update-deep &&
> diff --git a/t/t7114-reset-sparse-checkout.sh b/t/t7114-reset-sparse-checkout.sh
> new file mode 100755
> index 00000000000..a8029707fb1
> --- /dev/null
> +++ b/t/t7114-reset-sparse-checkout.sh
> @@ -0,0 +1,61 @@
> +#!/bin/sh
> +
> +test_description='reset when using a sparse-checkout'
> +
> +. ./test-lib.sh
> +
> +test_expect_success 'setup' '
> +       test_tick &&
> +       echo "checkout file" >c &&
> +       echo "modify file" >m &&
> +       echo "delete file" >d &&
> +       git add . &&
> +       git commit -m "initial commit" &&
> +       echo "added file" >a &&
> +       echo "modification of a file" >m &&
> +       git rm d &&
> +       git add . &&
> +       git commit -m "second commit" &&
> +       git checkout -b endCommit
> +'
> +
> +test_expect_success 'reset when there is a sparse-checkout' '
> +       echo "/c" >.git/info/sparse-checkout &&
> +       test_config core.sparsecheckout true &&
> +       git checkout -B resetBranch &&
> +       test_path_is_missing m &&
> +       test_path_is_missing a &&
> +       test_path_is_missing d &&
> +       git reset HEAD~1 &&
> +       echo "checkout file" >expect &&
> +       test_cmp expect c &&
> +       echo "added file" >expect &&
> +       test_cmp expect a &&
> +       echo "modification of a file" >expect &&
> +       test_cmp expect m &&
> +       test_path_is_missing d
> +'
> +
> +test_expect_success 'reset after deleting file without skip-worktree bit' '
> +       git checkout -f endCommit &&
> +       git clean -xdf &&
> +       cat >.git/info/sparse-checkout <<-\EOF &&
> +       /c
> +       /m
> +       EOF
> +       test_config core.sparsecheckout true &&
> +       git checkout -B resetAfterDelete &&
> +       test_path_is_file m &&
> +       test_path_is_missing a &&
> +       test_path_is_missing d &&
> +       rm -f m &&
> +       git reset HEAD~1 &&
> +       echo "checkout file" >expect &&
> +       test_cmp expect c &&
> +       echo "added file" >expect &&
> +       test_cmp expect a &&
> +       test_path_is_missing m &&
> +       test_path_is_missing d
> +'
> +
> +test_done
> --
> gitgitgadget
>
Previous: Junio C HamanoNext: Victoria Dye
Message 24 of 114 in “Sparse Index: integrate with reset”
  1. 0/7 Sparse Index: integrate with resetVictoria Dye via GitGitGadget, Sep 30, 2021
  2. 1/7 reset: behave correctly with sparse-checkoutKevin Willford via GitGitGadget, Sep 30, 2021
  3. Junio C HamanoSep 30, 2021
  4. Victoria DyeOct 1, 2021
  5. 2/7 sparse-index: update command for expand/collapse testVictoria Dye via GitGitGadget, Sep 30, 2021
  6. Taylor BlauSep 30, 2021
  7. Victoria DyeSep 30, 2021
  8. Junio C HamanoSep 30, 2021
  9. Victoria DyeSep 30, 2021
  10. Junio C HamanoOct 1, 2021
  11. Victoria DyeOct 4, 2021
  12. Bagas SanjayaOct 1, 2021
  13. 3/7 reset: expand test coverage for sparse checkoutsVictoria Dye via GitGitGadget, Sep 30, 2021
  14. 4/7 reset: integrate with sparse indexVictoria Dye via GitGitGadget, Sep 30, 2021
  15. 5/7 reset: make sparse-aware (except --mixed)Victoria Dye via GitGitGadget, Sep 30, 2021
  16. 6/7 reset: make --mixed sparse-awareVictoria Dye via GitGitGadget, Sep 30, 2021
  17. Victoria DyeOct 1, 2021
  18. 7/7 unpack-trees: improve performance of next_cache_entryVictoria Dye via GitGitGadget, Sep 30, 2021
  19. 0/7 Sparse Index: integrate with resetVictoria Dye via GitGitGadget, Oct 5, 2021
  20. 1/7 reset: behave correctly with sparse-checkoutKevin Willford via GitGitGadget, Oct 5, 2021
  21. Junio C HamanoOct 5, 2021
  22. Victoria DyeOct 5, 2021
  23. Junio C HamanoOct 6, 2021
  24. Elijah NewrenOct 6, 2021
  25. Victoria DyeOct 6, 2021
  26. Bagas SanjayaOct 6, 2021
  27. 3/7 reset: expand test coverage for sparse checkoutsVictoria Dye via GitGitGadget, Oct 5, 2021
  28. Elijah NewrenOct 6, 2021
  29. 4/7 reset: integrate with sparse indexVictoria Dye via GitGitGadget, Oct 5, 2021
  30. Elijah NewrenOct 6, 2021
  31. Junio C HamanoOct 6, 2021
  32. 2/7 update-index: add --force-full-index option for expand/collapse testVictoria Dye via GitGitGadget, Oct 5, 2021
  33. Elijah NewrenOct 6, 2021
  34. Victoria DyeOct 6, 2021
  35. Elijah NewrenOct 8, 2021
  36. Junio C HamanoOct 8, 2021
  37. Bagas SanjayaOct 6, 2021
  38. 5/7 reset: make sparse-aware (except --mixed)Victoria Dye via GitGitGadget, Oct 5, 2021
  39. Elijah NewrenOct 6, 2021
  40. Victoria DyeOct 6, 2021
  41. Bagas SanjayaOct 6, 2021
  42. 6/7 reset: make --mixed sparse-awareVictoria Dye via GitGitGadget, Oct 5, 2021
  43. Elijah NewrenOct 6, 2021
  44. Victoria DyeOct 7, 2021
  45. 7/7 unpack-trees: improve performance of next_cache_entryVictoria Dye via GitGitGadget, Oct 5, 2021
  46. Bagas SanjayaOct 6, 2021
  47. Ævar Arnfjörð BjarmasonOct 5, 2021
  48. Victoria DyeOct 5, 2021
  49. Elijah NewrenOct 6, 2021
  50. 0/8 Sparse Index: integrate with resetVictoria Dye via GitGitGadget, Oct 7, 2021
  51. 1/8 reset: rename is_missing to !is_in_reset_treeVictoria Dye via GitGitGadget, Oct 7, 2021
  52. 2/8 reset: preserve skip-worktree bit in mixed resetKevin Willford via GitGitGadget, Oct 7, 2021
  53. Junio C HamanoOct 8, 2021
  54. 3/8 update-index: add --force-full-index option for expand/collapse testVictoria Dye via GitGitGadget, Oct 7, 2021
  55. Bagas SanjayaOct 8, 2021
  56. Junio C HamanoOct 8, 2021
  57. Victoria DyeOct 8, 2021
  58. Junio C HamanoOct 8, 2021
  59. Derrick StoleeOct 11, 2021
  60. Victoria DyeOct 11, 2021
  61. Junio C HamanoOct 11, 2021
  62. 4/8 reset: expand test coverage for sparse checkoutsVictoria Dye via GitGitGadget, Oct 7, 2021
  63. 5/8 reset: integrate with sparse indexVictoria Dye via GitGitGadget, Oct 7, 2021
  64. 6/8 reset: make sparse-aware (except --mixed)Victoria Dye via GitGitGadget, Oct 7, 2021
  65. Phillip WoodOct 8, 2021
  66. Victoria DyeOct 8, 2021
  67. Junio C HamanoOct 8, 2021
  68. Phillip WoodOct 9, 2021
  69. Junio C HamanoOct 10, 2021
  70. Victoria DyeOct 11, 2021
  71. Junio C HamanoOct 11, 2021
  72. Phillip WoodOct 12, 2021
  73. Junio C HamanoOct 12, 2021
  74. Phillip WoodOct 12, 2021
  75. 7/8 reset: make --mixed sparse-awareVictoria Dye via GitGitGadget, Oct 7, 2021
  76. Elijah NewrenNov 20, 2021
  77. Victoria DyeNov 22, 2021
  78. 8/8 unpack-trees: improve performance of next_cache_entryVictoria Dye via GitGitGadget, Oct 7, 2021
  79. 0/8 Sparse Index: integrate with resetVictoria Dye via GitGitGadget, Oct 11, 2021
  80. 1/8 reset: rename is_missing to !is_in_reset_treeVictoria Dye via GitGitGadget, Oct 11, 2021
  81. 2/8 reset: preserve skip-worktree bit in mixed resetVictoria Dye via GitGitGadget, Oct 11, 2021
  82. Emily ShafferOct 22, 2021
  83. Victoria DyeOct 25, 2021
  84. 3/8 sparse-index: update command for expand/collapse testVictoria Dye via GitGitGadget, Oct 11, 2021
  85. 4/8 reset: expand test coverage for sparse checkoutsVictoria Dye via GitGitGadget, Oct 11, 2021
  86. 5/8 reset: integrate with sparse indexVictoria Dye via GitGitGadget, Oct 11, 2021
  87. 7/8 reset: make --mixed sparse-awareVictoria Dye via GitGitGadget, Oct 11, 2021
  88. 6/8 reset: make sparse-aware (except --mixed)Victoria Dye via GitGitGadget, Oct 11, 2021
  89. 8/8 unpack-trees: improve performance of next_cache_entryVictoria Dye via GitGitGadget, Oct 11, 2021
  90. 0/8 Sparse Index: integrate with resetVictoria Dye via GitGitGadget, Oct 27, 2021
  91. 1/8 reset: rename is_missing to !is_in_reset_treeVictoria Dye via GitGitGadget, Oct 27, 2021
  92. 2/8 reset: preserve skip-worktree bit in mixed resetVictoria Dye via GitGitGadget, Oct 27, 2021
  93. 3/8 sparse-index: update command for expand/collapse testVictoria Dye via GitGitGadget, Oct 27, 2021
  94. 4/8 reset: expand test coverage for sparse checkoutsVictoria Dye via GitGitGadget, Oct 27, 2021
  95. 5/8 reset: integrate with sparse indexVictoria Dye via GitGitGadget, Oct 27, 2021
  96. 6/8 reset: make sparse-aware (except --mixed)Victoria Dye via GitGitGadget, Oct 27, 2021
  97. 7/8 reset: make --mixed sparse-awareVictoria Dye via GitGitGadget, Oct 27, 2021
  98. Elijah NewrenNov 20, 2021
  99. Victoria DyeNov 22, 2021
  100. 8/8 unpack-trees: improve performance of next_cache_entryVictoria Dye via GitGitGadget, Oct 27, 2021
  101. Elijah NewrenNov 20, 2021
  102. 0/8 Sparse Index: integrate with resetVictoria Dye via GitGitGadget, Nov 29, 2021
  103. 1/8 reset: rename is_missing to !is_in_reset_treeVictoria Dye via GitGitGadget, Nov 29, 2021
  104. 2/8 reset: preserve skip-worktree bit in mixed resetVictoria Dye via GitGitGadget, Nov 29, 2021
  105. 3/8 sparse-index: update command for expand/collapse testVictoria Dye via GitGitGadget, Nov 29, 2021
  106. 4/8 reset: expand test coverage for sparse checkoutsVictoria Dye via GitGitGadget, Nov 29, 2021
  107. 5/8 reset: integrate with sparse indexVictoria Dye via GitGitGadget, Nov 29, 2021
  108. 6/8 reset: make sparse-aware (except --mixed)Victoria Dye via GitGitGadget, Nov 29, 2021
  109. 7/8 reset: make --mixed sparse-awareVictoria Dye via GitGitGadget, Nov 29, 2021
  110. 8/8 unpack-trees: improve performance of next_cache_entryVictoria Dye via GitGitGadget, Nov 29, 2021
  111. Elijah NewrenNov 29, 2021
  112. Victoria DyeNov 29, 2021
  113. Elijah NewrenNov 30, 2021
  114. Ævar Arnfjörð BjarmasonDec 1, 2021

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.