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

Re: Bug report: `git restore --source --staged` deals poorly with sparse-checkout

From
Martin von Zweigbergk <martinvonz@google.com>
Date
Oct 5, 2022, 20:00 UTC
Message-ID
<CAESOdVDt7SU=OJhF0mgyZ=B3sncB49aML8oOzKTKAnmGO5BaVQ@mail.gmail.com>
In-Reply-To
<CABPp-BH5_=Tq9DM6iAfG3+DuzEE7dR-H8rhP34x-A5FQhLO+bg@mail.gmail.com>
On Wed, Oct 5, 2022 at 12:51 AM Elijah Newren <newren@gmail.com> wrote:
Show 45 quoted lines
>
> On Tue, Oct 4, 2022 at 9:53 PM Martin von Zweigbergk
> <martinvonz@google.com> wrote:
> >
> > On Tue, Oct 4, 2022 at 1:35 PM Victoria Dye <vdye@github.com> wrote:
> > >
> > > Martin von Zweigbergk wrote:
> > > >> On Tue, Oct 4, 2022 at 9:34 AM Victoria Dye <vdye@github.com <mailto:vdye@github.com>> wrote:
> > > >>
> [...]
> > > >> Thanks for reporting this! There are a few confusing things going on with
> > > >> 'restore' here.
> > > >>
> > > >> First is that the out-of-cone was even restored in the first place.
> > > >>
> > > >
> > > > I was actually happy that the out-of-cone paths were restored. I ran that
> > > > command as an experiment while reading Elijah's doc because I was curious
> > > > what would happen. The reason I think it should restore out-of-cone paths is
> > > > so you can do `git restore --staged --source <some commit> && git commit -m
> > > > "restore to old commit"` without caring about the sparse spec.
> > >
> > > Conversely, that's behavior a user *wouldn't* want if they want to keep
> > > their sparse cone intact (not to mention the performance impact of checking
> > > out the entire worktree). I think it does more harm to those users than it
> > > would benefit the ones that want to checkout out-of-cone files.
> > >
> > > The use-case you're describing should be served by the
> > > '--ignore-skip-worktree-bits' option (not the most intuitive name,
> > > unfortunately). Luckily, there's an increasing desire to improve the naming
> > > of sparse-related options, so the UX situation should improve in the future.
> >
> > I realized after sending my previous email that I might have a
> > different view of what
> > sparse checkout is about. To me, it seems like it should be just a performance
> > optimization. That's why I feel like commands should behave the same way with
> > or without a sparse spec (unless that proposed `--restrict` flag is passed). I
> > understand if that's just not feasible. Sorry about the noise in that case :)
>
> The problem I see with that definition is that I'm not even sure what
> that means.  Behaving the same way with or without a sparse
> specification at the extreme means that switching branches should
> populate all the files in that branch...meaning a dense checkout.
> That kind of defeats the point.  So, I'm sure you don't mean that they
> behave the same in all cases...but where do you draw the line?

I agree with you and Stolee that there are two different cases: some people use sparse checkouts to restrict what they see (behavior A), and some people use it just as a performance optimization (behavior B). So I suspect we roughly agree about what should happen if you pass `--restrict` (or if that becomes the default so you don't actually need to pass it). My arguments were about the `--no-restrict` case. Sorry, I should have made that clear.

I also agree that having a way to make commands restrict to certain paths by default is useful, and I agree that tying that set of paths to the current worktree's sparse spec makes sense.

I'll answer the questions below for the `--no-restrict` case (behavior B).

Show 7 quoted lines
>
> Is it just switch/checkout & `reset --hard` that avoid reading and
> writing outside the sparse specification?
>
> Should diff & status ignore files outside the sparse specification
> even if users wrote to such files?  A "performance optimization" might
> suggest we should, but would users get confused?
I think they should be included (again, in the `--no-restrict` case).
>
> What about merge/rebase/cherry-pick/revert?  Should those write
> additional files to the working tree or avoid it?  What about if there
> are conflicts outside the sparse specification?

I think they should avoid it, but since the user will need to resolve that conflict anyway, I can see it makes sense to write them to disk if there are conflicts.

Show 5 quoted lines
>
> And if extra files get written outside the sparse specification, are
> there ways for this to get "cleaned up" where after resolving
> conflicts or changes we can again remove the file from the working
> tree?

I've never really used `git sparse-checkout` (until I read your doc), but isn't that what `git sparse-checkout reapply` is for?

Show 12 quoted lines
>
> What about `git grep PATTERN`?  That's documented to search the
> tracked files in the working tree.  But should that include the files
> that would have been there were it not for the "performance
> optimization" of not checking them out?  (Similarly, what about `git
> grep --cached PATTERN` or `git grep PATTERN REVISION`?)  I mean, if
> these commands should behave the same regardless of sparse
> specification, then you should search those other files, right?  But
> isn't that a nasty performance penalty if the user has a
> sparse/partial clone since Git will have to do many network operations
> to get additional blobs in order to search them?  Is that really
> wanted?

I think it's consistent to search them with `--no-restrict` (but not with `--restrict`, of course).

Show 6 quoted lines
>
> What about `git rm '*.png'` to remove all the tracked png files from
> my working tree.  Should that also remove all the files that would
> have been there were it not for the "performance optimization"?  Will
> that result in very negative surprises for those with a "I want to
> concentrate on just this subset of files" mental model?
Same here.
Show 5 quoted lines
>
> What about `git worktree add`?  Should the sparse specification be the
> same for all worktrees?  Be per-worktree?  Should it default to dense?
>  To just top-level sparse?  To the same sparsity as the worktree you
> were in when you created a new one?

That's an interesting case. If someone does `git worktree add` and expects all files to be available in the working copy, they might be surprised, yes. I think that's a much smaller risk than `git restore --source HEAD^ --staged && git commit -m 'undo changes'` being partial, however.

Previous: Elijah NewrenNext: Elijah Newren
Message 6 of 12 in “Bug report: `git restore --source --staged` deals poorly with sparse-checkout”
  1. Glen ChooOct 3, 2022
  2. Victoria DyeOct 4, 2022
  3. Victoria DyeOct 4, 2022
  4. Martin von ZweigbergkOct 5, 2022
  5. Elijah NewrenOct 5, 2022
  6. Martin von ZweigbergkOct 5, 2022
  7. Elijah NewrenOct 6, 2022
  8. Victoria DyeOct 5, 2022
  9. Elijah NewrenOct 5, 2022
  10. Junio C HamanoOct 6, 2022
  11. Junio C HamanoOct 6, 2022
  12. Elijah NewrenOct 5, 2022

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.