Skip to content

Resolve a worktree to its parent so directory commands work - #1200

Merged
geodro merged 2 commits into
mainfrom
fix/worktree-share
Jul 27, 2026
Merged

Resolve a worktree to its parent so directory commands work#1200
geodro merged 2 commits into
mainfrom
fix/worktree-share

Conversation

@geodro

@geodro geodro commented Jul 27, 2026

Copy link
Copy Markdown
Member

A worktree inherits its parent's registration and is deliberately never registered as a site of its own, but the shared resolver behind every directory scoped command looked a directory up by exact registry path. Inside a checkout that always missed, so the command offered to link the directory, link correctly refused because it is a worktree, and the caller then reported no site registered for this directory, run lerd link first. That is advice that can never succeed no matter how many times it is followed, and it took out share, open, domain, env, worker, runtime, stripe and xdebug pause all at once.

The resolver now falls back to the owning parent and the branch the checkout is on, ahead of the link prompt, so a worktree resolves silently instead of prompting for something that cannot be done.

Commands that address a domain act on the branch rather than the parent. lerd share tunnels the worktree's own subdomain, which would otherwise have been a quietly wrong site rather than an error. That needs a branch dimension on the tunnel registry, which was keyed by site name, so a worktree tunnel neither replaces the parent's nor is stopped along with it, and the Cloudflare named tunnel is keyed to the branch too so routing a hostname to a worktree cannot take over the one the parent site uses. The tunnel command builds against a target now, one domain and its TLS state, instead of reaching into the site for both. lerd open opens the branch domain for the same reason.

The dashboard share menu used to hide its whole public tunnel section while a worktree tab was active. It offers it now, reading and acting on that branch's tunnel, with the sites payload carrying the tunnel per worktree the way it already carries the LAN port, and the QR endpoint honouring the branch. Both tunnels can run at once, each on its own public URL, and stopping one leaves the other alone.

lerd lan:share and lan:unshare resolved the current directory through the queue site helper, whose fallback treats the directory basename as a site name, so inside a worktree they assigned a LAN port to a site that does not exist. Both route through the same resolver now and drive the per branch proxy that was already implemented and reachable from the dashboard.

Closes #1199

A worktree inherits its parent's registration and is deliberately never registered as a site of its own, but the shared resolver behind every directory scoped command looked a directory up by exact registry path. Inside a checkout that always missed, so the command offered to link the directory, link correctly refused because it is a worktree, and the caller then reported no site registered for this directory, run lerd link first. That is advice that can never succeed no matter how many times it is followed, and it took out share, open, domain, env, worker, runtime, stripe and xdebug pause all at once.

The resolver now falls back to the owning parent and the branch the checkout is on, ahead of the link prompt, so a worktree resolves silently instead of prompting for something that cannot be done.

Commands that address a domain act on the branch rather than the parent. lerd share tunnels the worktree's own subdomain, which needs a branch dimension on the tunnel registry so a worktree tunnel neither replaces the parent's nor is stopped along with it, and the Cloudflare named tunnel is keyed to the branch too so routing a hostname to a worktree cannot take over the one the parent site uses. The tunnel command now builds against a target, one domain and its TLS state, instead of reaching into the site for both. lerd open opens the branch domain for the same reason.

The dashboard share menu used to hide its whole public tunnel section while a worktree tab was active. It offers it now, reading and acting on that branch's tunnel, with the sites payload carrying the tunnel per worktree the way it already carries the LAN port, and the QR endpoint honouring the branch.

lerd lan:share and lan:unshare resolved the current directory through the queue site helper, whose fallback treats the directory basename as a site name, so inside a worktree they assigned a LAN port to a site that does not exist. Both route through the same resolver now and drive the per branch proxy that was already implemented and reachable from the dashboard.

Closes #1199
@geodro
geodro requested a review from a team as a code owner July 27, 2026 16:44
@geodro
geodro requested a review from a team July 27, 2026 16:44
The worktree lookup compared raw paths while the registry lookup has always compared canonical ones. A checkout under a symlinked parent is therefore spelled one way in the site registry and in git's own metadata and another by os.Getwd, so the two never matched and the checkout was not recognised as a worktree at all. macOS resolves /var to /private/var and ostree hosts resolve /home to /var/home, so this covers every install on either.

On those hosts the parent fallback silently never fired, and linking inside a worktree registered it as a site of its own rather than refusing, which is the outcome the check exists to prevent. Both sides are canonicalised now, the way the registry lookup does it.
@geodro
geodro merged commit d13c4ba into main Jul 27, 2026
3 checks passed
@geodro
geodro deleted the fix/worktree-share branch July 27, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Directory scoped commands dead end inside a git worktree

1 participant