Skip to content

fix(branch): include branches checked out in other worktrees - #2013

Merged
CKolkey merged 1 commit into
NeogitOrg:masterfrom
ethanstoner:fix/worktree-branches-in-pickers
Sep 28, 2026
Merged

CKolkey merged 1 commit into
NeogitOrg:masterfrom
ethanstoner:fix/worktree-branches-in-pickers

Conversation

@ethanstoner

Copy link
Copy Markdown

Bug

Branches that are checked out in a linked worktree never show up in the pickers built from git.branch (for example the diff popup's range picker, or "checkout recent branch").

Root cause

git branch marks each line with a prefix: * for the current branch, + for a branch checked out in another worktree, and two spaces for everything else. parse_branches in lua/neogit/lib/git/branch.lua only matched "^[* ] (.+)" / "^ (.+)", so any line starting with + was dropped, whatever include_current was set to.

list_related_branches (used by cherry-pick "harvest") parses the same output but only trimmed whitespace. Branches checked out in another worktree came back as + name, and the current branch as * name.

Change

  • parse_branches now also matches the + marker: "^[*+ ] (.+)" when the current branch is included, "^[+ ] (.+)" when it isn't. The current branch is still left out unless it's requested.
  • list_related_branches strips a leading * or + before trimming, so it returns plain branch names.

These are the only two places that parse git branch output. The other pickers (checkout, push, log, etc.) use git.refs, which reads for-each-ref and already listed these branches.

Behavior note: a branch checked out in another worktree is now selectable, the same way the git.refs-based checkout picker already offers it. If you try to check it out, git refuses with its usual "already used by worktree" error. Neogit doesn't add any extra filtering, so git's own rules still decide what's allowed.

Tests

Added a lib.git.branch with linked worktrees block to tests/specs/neogit/lib/git/branch_spec.lua. It sits outside the existing pending(...) block, so it actually runs. The spec creates a real temporary repo with git worktree add and checks that:

  • get_local_branches(false/true) and get_all_branches(false) include the branch checked out in the other worktree
  • the current branch is still excluded unless include_current is set
  • list_related_branches("--contains", ...) returns names without */+ markers

Before the fix, 3 of the 4 new tests fail. After the fix they all pass.

  • make test: all 17 spec files pass, 0 failures
  • bundle exec rspec (run locally on macOS with Neovim 0.12): upstream master already fails 67 of 519 examples here with the same seed, mostly screen-layout and default-branch mismatches in this environment. With this change, 68 fail. The difference is only in flaky examples (reflog, stash, bisect, push), and none of them depend on the parsing changed here. CI should give the real result.
  • selene --config selene/config.toml lua, typos and stylua --check lua/ tests/ are all clean

Fixes #2003

Thanks to @f1code for the detailed report, which pinned down the root cause and proposed this pattern fix.

Generated with Claude Code on behalf of @ethanstoner.

`git branch` prefixes branches checked out in a linked worktree with
"+ ", which parse_branches did not match, so those branches were
missing from pickers such as the diff range picker. Also strip the
"*"/"+" markers in list_related_branches.

Fixes NeogitOrg#2003
@CKolkey
CKolkey merged commit 209ba02 into NeogitOrg:master Sep 28, 2026
2 of 6 checks passed
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.

Branches checked out in a linked worktree are excluded from branch pickers (diff, checkout, etc.)

2 participants