Reputation: 3709
Background: recently setup a new laptop, and zip'd my repo up from the previous laptop and unzipped on the new laptop. Everything else seems to be working fine. I've never made a sparse checkout in this repo or on this machine.
$ git status
On branch develop
Your branch is up to date with 'origin/develop'.
You are in a sparse checkout with 100% of tracked files present.
$ git sparse-checkout list
warning: this worktree is not sparse (sparse-checkout file may not exist)
$ tree .git/info
.git/info
├── exclude
└── refs
I'm using worktrees, so I created a new worktree but it gives the same results. The above commands were run from the main worktree dir.
I found the command to disable a sparse checkout, but it doesn't appear to affect anything:
$ git sparse-checkout disable
$ git sparse-checkout disable --global
$ git status
On branch develop
Your branch is up to date with 'origin/develop'.
You are in a sparse checkout with 100% of tracked files present.
I'm pretty sure I could simply reclone the repo to make it go away, but I want to make sure this doesn't keep happening.
Running git config --get --bool core.sparsecheckout
does print true
, and the git config --list --show-origin
shows that it's coming from the local .git/config
file where I can see it's indeed true
. After running git sparse-checkout disable
and immediately cat
'g the file, I can see the value remains unchanged. Permissions on that file are 644
which I believe is ok.
While looking at .git/config
closer, I saw extensions.worktreeConfig = true
, though I don't have a corresponding config.worktree
(I am using worktrees though). I ran git config extensions.worktreeConfig false
and that value IS reflected in the file. Yet, if I run git sparse-checkout disable
again, it resets extensions.worktreeConfig
back to true
.
On a whim, I ran git config core.sparsecheckout false
and that seems to have made the expected change -- and even better, extensions.worktreeConfig
retained its value. And yes, git status
no longer mentions a "sparse checkout", which is great.
This is all on git v2.28.0. The docs page for git sparse-checkout
states: THIS COMMAND IS EXPERIMENTAL, so maybe I should take them seriously and consider this a bug :)
Upvotes: 3
Views: 7850
Reputation: 488013
Based on comments (and some poking around in the Git source), I can say that this seems to be a bug in some of the new sparse support, in terms of its interaction with a feature that first went into Git 2.20, namely extensions.worktreeConfig
, and what went out with Git 2.28.
To fix it, you should be able to run:
git config core.repositoryformatversion 1
(or, you can do what you did 😀).
The extensions.worktreeConfig
setting is, or at least was originally, intended for use with git worktree
. It causes Git to read two local (repository-specific) configuration files: the file named config
in the $GIT_DIR
(i.e., .git/config
), and the file named config.worktree
.
By itself, this feature seems useless: why read two separate files for one configuration? The trick here is that .git/config
applies to all added work-trees while each added work-tree has its own config.worktree
file. So you can configure different settings in each added work-tree: anything you want configured for all worktrees attached to this repository goes in .git/config
, and anything you want in one particular work-tree attached to this repository goes in $GIT_DIR/worktrees/<id>/config.worktree
(assuming it's an added work-tree and not the main one: the main one doesn't have a worktrees/
subdirectory so that one's file would be in $GIT_DIR/config.worktree
).
The interaction with sparse checkout itself is straightforward: sparse checkout is meant to be per-worktree. So any time you use git sparse-checkout
, Git tries to turn on the per-work-tree extension and set the configuration in each work-tree separately. But there's a bug here, not related directly to sparse checkout.
There is a much older setting in Git called core.repositoryformatversion
. This setting predates Git 1.0 (the oldest tag that contains the commit that adds it is v0.99.9l
, which was rc4 for Git 1.0). This setting was set at zero from the time it was created (2005) until extensions.*
were created back in 2015 ([commit 00a09d57eb8a041e6a6b0470c53533719c049bab
(https://github.com/git/git/commit/00a09d57eb8a041e6a6b0470c53533719c049bab)). All extensions (extensions.*
settings) are supposed to require core.repositoryformatversion
to be set to 1
, so as to enable them. But in fact, they didn't.
For Git version 2.28.0, Git added code to check the above requirement. If core.repositoryformatversion
was set to zero, all extensions were disabled. Once set to 1, the extensions become enabled.
Unfortunately, programs like git sparse-checkout
would use the extensions, without first setting core.repositoryformatversion
. Before Git 2.28, this worked. So all these experimental commands worked, as far as things went. But then the long-standing bug got fixed, which broke everything using extensions.1
In Git 2.29, I believe Git either notices and warns about the wrong repositoryformatversion
setting, or fixes it automatically. (I have not checked or tested this.)
1The main other user of extensions is probably the partial clone stuff, enabled via extensions.partialClone
and extensions.partialCloneRemote
. The others are extensions.objectFormat
, extensions.preciousObjects
, and of course extensions.worktreeConfig
.
Upvotes: 3