Fix clone authentication when includeIf is in git config - #2100
Open
tyrielv wants to merge 1 commit into
Open
Conversation
'gvfs clone' failed to authenticate when the user's git config contained an
'includeIf "gitdir:..."' section:
Cannot clone because authentication failed:
fatal: Invalid path '<root>/src': No such file or directory
Clone authenticates before it creates the enlistment, but the credential verbs
ran against the enlistment's .git folder through --git-dir. Git resolves that
path before it evaluates an includeIf condition, so git aborted instead of
asking for credentials. The condition did not need to match. Any 'gitdir:'
condition was enough.
Pass --git-dir only when .git exists. Credential helpers still see repo-local
configuration in an established enlistment, and there is no local configuration
to read before clone creates the repository. A linked worktree stores .git as a
file rather than a folder, so accept both. Git resolves the 'gitdir:' pointer in
that file, so the shared repository's configuration is still used.
Route the other two pre-repository git calls the same way. Both hit the same
failure during clone:
- TryGetConfigUrlMatch runs from the GitAuthentication constructor. When it
failed, GitSsl was never built and the user's client-certificate settings
were silently dropped.
- TryGetCertificatePassword is itself a credential fill.
Record which route ran in the credential failure metadata, so a later report of
"the wrong credentials were used" can be diagnosed from the logs.
Add unit tests for all three states of .git (missing, folder, worktree file)
across all three credential verbs, and functional tests that clone with and
without an includeIf section. The functional tests assert that authentication
was reached, not only that the failure message changed: a clone that cannot
reach the server also exits with the same code and prints neither of the
strings under test, so absence checks alone would pass with no network.
Also correct two entries in AGENTS.md that this work proved wrong. GVFS.Payload
has no ProjectReference items and never builds or publishes the projects
layout.bat copies from, so a stale binary can be packaged and tested silently.
And RunFunctionalTests-Dev.ps1 binds positional arguments to -Arch, so a bare
'Debug --test=...' fails validation.
Assisted-by: Claude Opus 5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
tyrielv
force-pushed
the
tyrielv/fix-clone-includeif
branch
from
August 28, 2026 22:41
6fe24c8 to
15a0fc0
Compare
tyrielv
marked this pull request as ready for review
August 28, 2026 22:52
tyrielv
enabled auto-merge
August 28, 2026 22:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
gvfs clonecannot authenticate when the user's git config contains anincludeIf "gitdir:..."section. The clone fails with:Cause
Clone authenticates before it creates the enlistment, but the credential verbs
run against the enlistment's
.gitfolder through--git-dir:CloneVerbbuilds aGVFSEnlistmentwhoseGitProcesstargets<root>\src\.git.CloneVerbauthenticates. Only<root>exists at this point.TryGetCredentialrunsgit credential fillwith--git-dir="<root>\src\.git".includeIfcondition, does notfind it, and aborts before it asks for credentials.
The condition does not have to match. Git resolves the repository path before it
compares the pattern, so any
gitdir:condition triggers the failure. AnincludeIf "onbranch:..."condition does not, because it needs no path.This affects VFS for Git only. Plain
git clonereaches the credential helpernormally with the same config.
Fix
Pass
--git-dironly when.gitexists. Credential helpers still see repo-localconfiguration in an established enlistment. Before clone creates the repository
there is no repo-local configuration to read, so nothing is lost by omitting it.
A linked worktree stores
.gitas a file that points at the real git directoryrather than as a folder, so the check accepts both. Git resolves the
gitdir:pointer in that file, so the shared repository's configuration is still used.
Two other pre-repository git calls are routed the same way, because they fail
identically during clone:
TryGetConfigUrlMatchruns from theGitAuthenticationconstructor. When itfailed,
GitSslwas never constructed and the user'shttp.sslCert/client-certificate configuration was silently dropped.
TryGetCertificatePasswordis itself acredential fill.Without these, a user with
includeIfand certificate authentication wasstill broken.
The fix is deliberately narrow. Always running the credential verbs outside the
enlistment would also fix the reported failure, but it would stop credential
helpers from reading a repository's local
credential.*configuration afterclone. Four of the new unit tests fail if someone widens it that way.
The chosen route is recorded in the credential failure metadata, so a later
report of "the wrong credentials were used" can be diagnosed from the logs.
Tests
New unit tests cover all three states of
.git, for all three credential verbs(
fill,approve,reject):.gitstate--git-dirpassedNew functional tests clone with and without an
includeIfsection and confirmthat both reach the credential helper. The test without the section is the
control: it passes before and after this change, which shows the other test fails
only because of the
includeIfsection.The functional tests assert that authentication was actually reached, not only
that the failure message changed. A clone that cannot reach the server exits with
the same code and prints neither of the strings under test, so absence checks
alone would pass with no network and prove nothing.
Verified by mutation. Forcing
--git-diron always fails 3 unit tests. Droppingit always fails 4. A real clone of an authenticated repository with an
includeIfsection fails on the unfixed build and succeeds on the fixed one.
Branch
This targets
vnextrather thanmaster. The defective code path is identicalin
v1.0.26014.1, so this is a long-standing defect and not a 2.0 regression.It changes runtime behavior on the credential path, so it soaks in
vnext.Also included
Two corrections to
AGENTS.mdthat this work proved wrong:GVFS.Payloadhas noProjectReferenceitems and never builds or publishesthe projects
layout.batcopies from. A project you did not publish contributesa binary from an earlier build, so the functional tests can silently exercise
stale code. The documented steps now publish each changed project explicitly and
show how to confirm the payload actually changed.
RunFunctionalTests-Dev.ps1binds positional arguments to-Arch, soRunFunctionalTests-Dev.ps1 Debug --test=...fails itsValidateSet. Thedocumented invocations now name both parameters.