Summary
RequiredGitConfig unconditionally force-writes core.repositoryformatversion = 0 into the enlistment's local config. That value is re-asserted on clone, on every mount, and on repair. Any repository that legitimately uses a git repo-format-v1 extension is therefore bricked — every git command fails — and because mount re-applies the setting, a user cannot repair it by hand.
Today this is reachable via a global git config, and it becomes the default path as git moves toward reftable.
Where
GVFS/GVFS.Common/Git/RequiredGitConfig.cs:96
// This is to match what git init does.
{ "core.repositoryformatversion", "0" },
GetRequiredSettings is documented as returning settings that "override any existing local configuration values," and is applied at:
GVFS/GVFS/CommandLine/CloneVerb.cs:696 — TrySetRequiredGitConfigSettings
GVFS/GVFS.Mount/InProcessMount.cs:290 — TrySetRequiredGitConfigSettings, i.e. every mount
GVFS/GVFS/RepairJobs/GitConfigRepairJob.cs:87 — repair
The write is not "set if absent." In GVFSVerb.TrySetConfig (GVFS/GVFS/CommandLine/GVFSVerb.cs:680-683), isRequired: true means an existing value that differs is overwritten:
if (!existingConfigSettings.TryGetValue(setting.Key, out existingSetting) ||
(isRequired && !existingSetting.HasValue(setting.Value)))
{
GitProcess.Result setConfigResult = git.SetInLocalConfig(setting.Key, setting.Value);
So an existing repositoryformatversion = 1 is actively downgraded to 0, while the extensions.* key that required v1 is left in place.
Reproduction
Any v1 extension triggers it. Ref storage is the most relevant one, and init.defaultRefFormat is honored by git today:
$ git -c init.defaultRefFormat=reftable init /tmp/r
$ grep -E 'repositoryformatversion|refstorage' /tmp/r/.git/config
refstorage = reftable
repositoryformatversion = 1
# what GVFS force-writes on clone, on every mount, and on repair:
$ git -C /tmp/r config core.repositoryformatversion 0
$ git -C /tmp/r status
fatal: repo version is 0, but v1-only extension found:
refstorage
Object format behaves identically:
$ git init --object-format=sha256 /tmp/s
$ git -C /tmp/s config core.repositoryformatversion 0
$ git -C /tmp/s status
fatal: repo version is 0, but v1-only extension found:
objectformat
Verified with git 2.55.0.vfs.0.8.
Why it matters now
init.defaultRefFormat=reftable and init.defaultObjectFormat=sha256 are honored by current git. A user who has set either globally gets a broken enlistment from gvfs clone today.
- Reftable is the direction git is moving for default ref storage, so this shifts from "user opted in" to "happens by default" without any change on the VFS for Git side.
- The failure is not a clean error. The enlistment is unusable, the message points at git internals rather than at VFS for Git, and mount re-applies the bad value — so hand-editing
.git/config back to 1 is undone on the next mount. That makes it hard to diagnose and effectively unrecoverable without knowing to look here.
Note that #2115 pins git init --object-format=sha1 during clone, which closes the sha256 axis for newly cloned enlistments. It does not address ref format, and it does not address a repo that reaches v1 by any other route, because the root cause is this force-write rather than the init defaults.
Suggested fix
Preferred: stop writing core.repositoryformatversion at all. The comment says the intent is "to match what git init does" — but git init already sets it correctly, so re-asserting it gains nothing and re-asserting it is exactly what does the damage. Dropping the key from the required set makes GVFS inherit whatever git chose, which is the correct value by construction.
Alternative, if an explicit guard is wanted: validate instead of write. If the repository is not a shape VFS for Git supports, fail the clone/mount with a clear message (for example "VFS for Git requires a sha1 repository with files ref storage") rather than writing a config value that breaks git. A git rev-parse --show-object-format / --show-ref-format check is cheap and gives a diagnosable error.
Either way it's worth auditing the rest of the required set for other settings that assert a value git is already responsible for — core.bare and core.logallrefupdates carry the same "for consistency with git init" comment and the same latent shape.
Related: #1033 (fast-fail via config extensions when using an incorrect git binary) is adjacent — both are about GVFS and git disagreeing on repository format expectations.
Summary
RequiredGitConfigunconditionally force-writescore.repositoryformatversion = 0into the enlistment's local config. That value is re-asserted on clone, on every mount, and on repair. Any repository that legitimately uses a git repo-format-v1 extension is therefore bricked — every git command fails — and because mount re-applies the setting, a user cannot repair it by hand.Today this is reachable via a global git config, and it becomes the default path as git moves toward reftable.
Where
GVFS/GVFS.Common/Git/RequiredGitConfig.cs:96GetRequiredSettingsis documented as returning settings that "override any existing local configuration values," and is applied at:GVFS/GVFS/CommandLine/CloneVerb.cs:696—TrySetRequiredGitConfigSettingsGVFS/GVFS.Mount/InProcessMount.cs:290—TrySetRequiredGitConfigSettings, i.e. every mountGVFS/GVFS/RepairJobs/GitConfigRepairJob.cs:87— repairThe write is not "set if absent." In
GVFSVerb.TrySetConfig(GVFS/GVFS/CommandLine/GVFSVerb.cs:680-683),isRequired: truemeans an existing value that differs is overwritten:So an existing
repositoryformatversion = 1is actively downgraded to0, while theextensions.*key that required v1 is left in place.Reproduction
Any v1 extension triggers it. Ref storage is the most relevant one, and
init.defaultRefFormatis honored by git today:Object format behaves identically:
Verified with git 2.55.0.vfs.0.8.
Why it matters now
init.defaultRefFormat=reftableandinit.defaultObjectFormat=sha256are honored by current git. A user who has set either globally gets a broken enlistment fromgvfs clonetoday..git/configback to1is undone on the next mount. That makes it hard to diagnose and effectively unrecoverable without knowing to look here.Note that #2115 pins
git init --object-format=sha1during clone, which closes the sha256 axis for newly cloned enlistments. It does not address ref format, and it does not address a repo that reaches v1 by any other route, because the root cause is this force-write rather than the init defaults.Suggested fix
Preferred: stop writing
core.repositoryformatversionat all. The comment says the intent is "to match what git init does" — butgit initalready sets it correctly, so re-asserting it gains nothing and re-asserting it is exactly what does the damage. Dropping the key from the required set makes GVFS inherit whatever git chose, which is the correct value by construction.Alternative, if an explicit guard is wanted: validate instead of write. If the repository is not a shape VFS for Git supports, fail the clone/mount with a clear message (for example "VFS for Git requires a sha1 repository with files ref storage") rather than writing a config value that breaks git. A
git rev-parse --show-object-format/--show-ref-formatcheck is cheap and gives a diagnosable error.Either way it's worth auditing the rest of the required set for other settings that assert a value git is already responsible for —
core.bareandcore.logallrefupdatescarry the same "for consistency with git init" comment and the same latent shape.Related: #1033 (fast-fail via config extensions when using an incorrect git binary) is adjacent — both are about GVFS and git disagreeing on repository format expectations.