What's wrong
GitInitBuilder.ProbeAsync (GitIntegration/Builders/GitInitBuilder.cs, around lines 128-147) decides whether a repository already exists at the target by running git rev-parse --git-dir. It returns true only when the answer is .git or .. The comment there assumes an absolute path always means "a repository exists, but as an ancestor, not here".
That assumption is false. git also prints an absolute path for a repository right at the target when its .git is a file pointing elsewhere, which covers:
- a checked-out submodule (
.git → ../.git/modules/x)
- a linked worktree (
.git → <main>/.git/worktrees/x)
- a repository created with
--separate-git-dir
Repro (git 2.43):
$ git init --separate-git-dir /tmp/sg s
$ git -C s rev-parse --git-dir
/tmp/sg
$ git init s
Reinitialized existing Git repository in /tmp/sg/
Failure scenario
Init(path) on any of those directories re-initializes the existing repository, yet GitInitResult.AlreadyExisted is false. The probe exists so callers learn that git re-initialized and silently ignored options such as --initial-branch (see CLAUDE.md). In these cases the caller is told a fresh repository was created with its requested initial branch, and neither is true.
Suggested fix
Compare paths rather than matching literal strings:
- Non-bare: the repository is "here" when
git -C <target> rev-parse --show-toplevel resolves to the same directory as the target, after normalizing both with Path.GetFullPath and resolving symlinks.
- Bare:
rev-parse --is-bare-repository is true and --absolute-git-dir equals the target.
- Anything else, including an ancestor repository or a non-zero exit, is "not yet".
Acceptance criteria
Tests where AlreadyExisted is true for:
- a
--separate-git-dir repository
- a linked worktree (
git worktree add)
and still false for a plain subdirectory of an existing repository.
What's wrong
GitInitBuilder.ProbeAsync(GitIntegration/Builders/GitInitBuilder.cs, around lines 128-147) decides whether a repository already exists at the target by runninggit rev-parse --git-dir. It returns true only when the answer is.gitor.. The comment there assumes an absolute path always means "a repository exists, but as an ancestor, not here".That assumption is false. git also prints an absolute path for a repository right at the target when its
.gitis a file pointing elsewhere, which covers:.git→../.git/modules/x).git→<main>/.git/worktrees/x)--separate-git-dirRepro (git 2.43):
Failure scenario
Init(path)on any of those directories re-initializes the existing repository, yetGitInitResult.AlreadyExistedisfalse. The probe exists so callers learn that git re-initialized and silently ignored options such as--initial-branch(see CLAUDE.md). In these cases the caller is told a fresh repository was created with its requested initial branch, and neither is true.Suggested fix
Compare paths rather than matching literal strings:
git -C <target> rev-parse --show-toplevelresolves to the same directory as the target, after normalizing both withPath.GetFullPathand resolving symlinks.rev-parse --is-bare-repositoryistrueand--absolute-git-direquals the target.Acceptance criteria
Tests where
AlreadyExistedistruefor:--separate-git-dirrepositorygit worktree add)and still
falsefor a plain subdirectory of an existing repository.