Skip to content

Support git worktrees in the branch picker - #11

Open
NetanelDavid wants to merge 3 commits into
idobh2:masterfrom
NetanelDavid:support-worktrees
Open

Support git worktrees in the branch picker#11
NetanelDavid wants to merge 3 commits into
idobh2:masterfrom
NetanelDavid:support-worktrees

Conversation

@NetanelDavid

@NetanelDavidNetanelDavid commented Jun 23, 2026

Copy link
Copy Markdown

What & why

Branches checked out in another git worktree currently leak into the list as un-actionable + branch entries — git refuses to checkout or branch -D them, so picking one just errors. This PR makes worktrees first-class in both flows.

Changes

  • Detect worktrees via git worktree list --porcelain, mapping each to its path. The list keeps git's + marker so it looks like git branch.
  • Checkout mode — selecting a worktree opens a new shell in that directory (type 'exit' to return). A CLI can't cd its parent shell, so spawning a shell is the portable equivalent; it uses $SHELL (or ComSpec/PowerShell on Windows), so it works across OSes and terminals. Regular branches still git checkout.
  • Delete mode (-d) — selecting a worktree runs git worktree remove (the branch is kept); regular branches still git branch -D. Removals run per-item, so a dirty/locked worktree is skipped with a clear message instead of aborting the whole selection.
  • Fix preselect — the autocomplete prompt matches default against a choice value, not an index, so the current branch is now actually highlighted by default (it never was before).
  • Docs — new README "Worktrees" section + updated -h help; version bumped to 1.1.0.

No new flags; behavior for existing branch workflows is unchanged.

Screen.Recording.2026-06-24.at.0.46.23.mov

Testing

Verified end-to-end against real worktrees by driving the interactive CLI through a PTY harness:

  • worktrees render with + and the current branch is preselected
  • selecting a worktree spawns a shell in it (pwd confirmed) and exit returns
  • -d on a worktree removes it while the branch survives
  • a dirty worktree is skipped gracefully (relays git's --force hint), no crash

🤖 Generated with Claude Code

Netanel Davidand others added 2 commits June 24, 2026 00:41
Worktree branches are now first-class in both the checkout and delete
flows instead of appearing as un-actionable "+ branch" entries that
git refuses to check out or delete.
- Detect worktrees via `git worktree list --porcelain` and map each to
its path; keep git's "+" marker in the list display.
- Checkout mode: selecting a worktree opens a new shell in that
directory (a CLI can't cd its parent shell), cross-platform via
$SHELL / ComSpec. Regular branches still `git checkout`.
- Delete mode (-d): selecting a worktree runs `git worktree remove`
(kept per-item so a dirty/locked one is skipped with a message rather
than aborting the batch); regular branches still `git branch -D`.
- Fix default selection: the autocomplete prompt matches `default`
against a choice value, not an index, so the current branch is now
actually preselected.
- Docs: README "Worktrees" section + help text; bump to 1.1.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@NetanelDavid

Copy link
Copy Markdown
Author

@idobh2 Please review

- Restore CRLF line endings in index.js so the diff vs master is
line-by-line reviewable again (new code files match).
- Replace exec(string) with an execFile-based git(args) helper so
branch names and worktree paths are never shell-interpolated
(also covers the pre-existing checkout / branch -D cases).
- Fix the dead `isOtherWorktree` condition: a '+' branch whose
worktree path can't be resolved is now reported with a note
instead of silently falling back to a regular branch.
- Extract the porcelain/branch-list parsers into parse.js and add
unit tests (node --test, no new deps). The tests caught two real
bugs: trim().slice(2) ate two chars off the first sorted branch
name, and the HEAD-> pointer filter only handled 'origin'.
- Anchor the HEAD-> filter so a branch literally named 'a->b' works.
- Compare worktree paths via realpath so symlinked toplevels
(macOS /var vs /private/var) still match.
- README: drop the PowerShell claim (code uses SHELL/ComSpec/cmd).
- Trim the 'Command failed' echo from worktree-removal errors.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto 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.

1 participant

@NetanelDavid