Repository navigation
Support linked worktrees and submodules, where .git is a file - #146
Merged
Merged
Conversation
In a linked worktree or a submodule `.git` is a file ("gitdir: ..."), not a
directory, so every `<repo>/.git/tracybot/...` path failed: init.py crashed
with NotADirectoryError (a submodule got no config, no hooks and no
snapshots), the agent plugins couldn't find the config, and writing the
Research Mode consent file threw ENOTDIR.
Resolve the real location instead. Everything Tracybot keeps under the git
dir lives in the *common* git dir, the same place the hooks are installed
and where pre-commit.py already reads the config from (the parent of the
hooks dir), so init and consent are per repository, not per worktree.
- init.py, post-fetch.py: ask git via `rev-parse --git-common-dir`
- opencode/claude-code/codex plugins and the extension's repoConsent.ts:
new resolveGitDir() that follows the `.git` file and the worktree's
`commondir` pointer (no git process needed)
- tests use real linked worktrees and submodules
tracyInitCheck.ts is left alone on purpose: #145 rewrites that code.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
init.py now writes the config to the common git dir, but tracyInitCheck still looked for <repo>/.git/tracybot/config. In a linked worktree that path can't exist, so initialization succeeded yet the extension kept treating the worktree as uninitialized and re-ran init (and re-showed the "repository initialized" message) on every activation. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.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.
Problem
In a linked worktree or a submodule,
.gitis a file (gitdir: ...), not a directory, so every<repo>/.git/tracybot/...path breaks. Found while reviewing #145; this is already broken onmain, not a regression from that PR.Reproduced on real repos (plain repo vs linked worktree vs submodule), running the real
init.pyand then a realgit committhrough the installed hooks:init.pybeforeinit.pyafterNotADirectoryErrorNotADirectoryError: no config, no hooks, no snapshots at allSame assumption elsewhere: the three agent plugins couldn't find the config (so nothing was recorded), and writing the Research Mode consent file (
repoConsent.ts) threwENOTDIR, e.g. clicking "I agree to share my data" in a worktree.Fix
Resolve the real location instead of assuming
.git/. Everything Tracybot keeps under the git dir goes in the common git dir. That is where the hooks are installed and wherepre-commit.pyalready reads the config from (the parent of the hooks dir), so init and consent are per repository, not per worktree.init.py,post-fetch.py:git rev-parse --git-common-dirrepoConsent.ts: newresolveGitDir()that follows the.gitfile and the worktree'scommondirpointer. No git process needed.vscode-extension/src/gitDir.tsis the reusable one.Related: #145
tracyInitCheck.ts(the extension's check for "is this repo initialized?") now goes throughresolveGitDirtoo, otherwise init would succeed in a worktree while the extension kept thinking it was uninitialized and re-ran it on every activation. #145 rewrites that code and moves it into a newinitState.ts, so whichever of the two merges second needs a small conflict resolution, andinitState.tsmust useresolveGitDir(fromsrc/gitDir.ts) as well. Use the common dir, notgit rev-parse --git-path: that gives a per-worktree path that the hooks don't read.post-fetch.pyisn't a hook name git actually runs, so that change is for consistency only.Testing
vscode-extensionunit tests: 66/66 (newgitDir.test.tswith a real linked worktree and submodule, plus a consent round-trip from a worktree)claude-code-pluginandcodex-pluginbun test: 12/12 each (new tests forresolveTracyPathin a worktree and a submodule)init.py+ real hooked commit in a plain repo, linked worktree and submodule, before and after (table above)🤖 Generated with Claude Code