feat(nvim): git worktree picker that follows open buffers #1
Reference in New Issue
Block a user
Delete Branch "unkin-agent/dotfiles:benvin/worktree-picker"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Jumping between agentws worktrees of the same repo meant quitting nvim or hand-reopening every buffer at the new path.
lua/func/worktree.lua, parsinggit worktree list --porcelainfor the current buffer's repo.cds to that worktree root and re-points each file buffer at the same relative path, restoring cursor position.b:worktree_orphan; refuse the switch if a modified buffer would be replaced.vim.ui.select.<Leader>gw, add:Worktree [path], addtests/worktree_spec.lua.Review of the worktree picker (correctness only; PR is atomic and the body follows conventions — no split or format issues).
func/worktree.lua
M.switch'sold_root(lines ~151-153) is derived fromdetect_root(context_dir()), i.e. the repo of whatever buffer/cwd is currently active.context_dir()'s own comment says it's deliberately meant to keep working "after wandering into another repo" — butswitch()reuses that same context to decide which buffers to carry over. If the active buffer/cwd isn't in the same worktree as your other open file buffers (e.g. you're browsing a different repo's worktree list, or sitting in a help/scratch buffer whose cwd resolved elsewhere),old_rootis wrong,contains(old_root, ...)matches nothing, and the switch silently reports "0 buffer(s) moved" with no warning that anything's off.Cursor capture only reads
wins[1](line ~190) when a buffer is open in multiple split windows, then reapplies that single cursor to every window showing it after the move (lines ~208-212) — per-window cursor divergence is lost.restore_cursor(lines ~127-131): for an empty destination file,rowbecomes0, producing an invalidnvim_win_set_cursor(win, {0, ...}). It's wrapped inpcallso it won't error, but it silently no-ops instead of e.g. placing the cursor at line 1 — worth a guard rather than relying on the swallow.None of these are blocking (the tested/common paths work), but especially #1 is worth a fix or at least a documented caveat before this becomes muscle memory.
Review: neovim git-worktree picker
Looked closely at buffer-to-worktree resolution, per-window cursor capture/restore, and cursor clamping.
contains()correctly boundary-checks with a trailing/(avoidsdotfilesmatchingdotfiles__branch),source_roots()sorts candidate roots longest-first so a worktree nested inside another wins the prefix match (worktree.lua:157-181, root_of at 183-190), per-window cursor capture/restore (worktree.lua:246-281) andclamp_cursor(worktree.lua:146-150) are both correct and match test expectations.source_rootsexists specifically to resolve that case correctly, but no test constructs a real nested worktree (e.g.otherliving atmain/.worktrees/other) to proveroot_ofpicks the inner root over the outer one. Worth a follow-up test since this is the one piece of "ownership resolution" logic that is unexercised.moved. Matches the stated "refuse the switch" behavior in the PR body, just flagging so its all-or-nothing semantics are a deliberate choice.Nothing here blocks merge; the nested-worktree test gap is the only actionable follow-up.
This should be managed via yadm
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.