Document why GitProcess does not use Enlistment.DotGitRoot - #2102
Draft
tyrielv wants to merge 1 commit into
Draft
Conversation
In a linked git worktree, Enlistment.DotGitRoot and the git directory that
GitProcess passes as --git-dir point at different locations:
Enlistment.DotGitRoot -> the shared .git directory of the main repo
GitProcess git dir -> "<worktree>\.git", a file holding
"gitdir: <shared>/.git/worktrees/<name>"
The two values look inconsistent, but each is correct for its purpose. Git
follows the gitdir: pointer, so the worktree .git file resolves the
per-worktree state (HEAD, index, per-worktree refs, reflog) and, through
commondir, the shared state (config, objects, packed-refs). DotGitRoot is used
for shared state that GVFS reads or writes directly on disk (objects,
objects/info/alternates, hooks).
Making GitProcess use DotGitRoot would be a regression. Every command would
bind to the main worktree. From inside a linked worktree, "rev-parse HEAD" and
"name-rev --name-only HEAD" would report the main worktree's branch and commit.
No behavior changes. This adds comments on both sides of the divergence, a
GitProcess.GitDirectoryPath accessor, and tests that pin the current values.
The new test fails if GitProcess is changed to read Enlistment.DotGitRoot.
Assisted-by: Claude Opus 4.5
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
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.
Summary
In a linked git worktree,
Enlistment.DotGitRootand the git directory thatGitProcesspasses as--git-dirpoint at different locations:Enlistment.DotGitRoot.gitdirectory of the main repoGitProcessgit dir<worktree>\.git— a file holdinggitdir: <shared>/.git/worktrees/<name>This looks like an inconsistency. It is not. Each value is correct for its own purpose, and the divergence is load-bearing.
Git follows the
gitdir:pointer, so the worktree.gitfile resolves the per-worktree state (HEAD, index, per-worktree refs, reflog) and, throughcommondir, the shared state (config, objects,packed-refs).DotGitRootis used for shared state that VFS for Git reads or writes directly on disk (objects,objects/info/alternates, hooks).Why "aligning" the two would be a regression
Changing
GitProcessto readEnlistment.DotGitRootbinds every command to the main worktree. Verified against a real worktree with divergentHEADs (git 2.55):--git-dirrev-parse --abbrev-ref HEADlog -1 --format=%s HEAD<worktree>\.git(current behavior)feature✅onfeature✅<shared>\.git(DotGitRoot)main❌onmaster❌So from inside a linked worktree,
rev-parse,name-rev,branch,symbolic-ref,update-ref, andread-treewould all silently operate on the wrong worktree.The second
GitProcess(gitBinPath, workingDirectoryRoot)constructor needs no change — it has noEnlistmentto consult, and its computed path is already the correct one.What this PR changes
Nothing functional. It documents the divergence and pins it with tests so a future "cleanup" cannot quietly introduce the regression above.
GitProcess.cs— comment explaining why the git dir is deliberately notEnlistment.DotGitRoot; newGitDirectoryPathaccessor so the value is testable.GVFSEnlistment.cs— comment recording thatDotGitRootis shared-state-only, and that per-worktree paths must come fromWorktree.WorktreeGitDir(asGitIndexPathalready does).WorktreeEnlistmentTests.cs— two tests pinning the current values.Testing
GitProcessreadingEnlistment.DotGitRoot) failsGitProcessUsesWorktreeGitFileNotSharedGitDirand nothing else, confirming the new test actually pins the behavior.Note for reviewers
The audit behind this PR also found callers that use
DotGitRootfor genuinely per-worktree state, whereGitIndexPathalready resolves correctly —FileSystemCallbacks.cs(watches the main repo'slogs/HEAD),GitIndexGenerator.cs,RepairJobs/GitIndexRepairJob.cs,DehydrateVerb.cs, andFastFetch/CheckoutPrefetcher.cs. Those are real divergences with real blast radius, and are deliberately left out of this PR to keep it a no-op. They will be evaluated separately.Targets
vnext: long-standing behavior, not a 2.0 regression.