You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
git gtr ai/go fails when branch is checked out in main working tree #127
When a branch is checked out in the main working tree (not a linked worktree), git gtr ai <branch> and git gtr go <branch> fail with "Worktree not found for branch", even though git worktree list correctly shows it.
The root cause is that resolve_target()/resolve_worktree() only searches linked worktrees in the worktrees directory and does not consider the main working tree as a valid match.
This is distinct from #123, which was about discover_repo_root() returning the wrong path when called from inside a linked worktree.
Steps to reproduce
# Main repo has branch checked outcd~/Code/my-repo
git checkout my-feature-branch
# git worktree list shows it correctly
git worktree list
# /Users/me/Code/my-repo abc1234 [my-feature-branch]# /Users/me/Code/my-repo-worktrees/other def5678 [other-branch]# But git gtr can't find it
git gtr ai my-feature-branch
# [x] Worktree not found for branch: my-feature-branch
git gtr go my-feature-branch
# [x] Worktree not found for branch: my-feature-branch
Expected behaviour
git gtr should recognise the main working tree when resolving a branch name, falling through to it when no linked worktree matches.
The issue occurs because resolve_target() in file:lib/core.sh (lines 258-310) doesn't properly recognize when a branch is checked out in the main working tree. While there is code at lines 274-279 that attempts to check if the identifier matches the current branch in the repo root, it appears this logic may not be working correctly or may have edge cases. The function only searches linked worktrees in the worktrees directory (lines 282-300) and doesn't fall back to checking if the branch exists in the main repo when no linked worktree matches.
Approach
The fix involves enhancing the resolve_target() function to properly detect when a branch is checked out in the main working tree. The existing check at lines 274-279 should be verified and potentially improved to handle all edge cases. Additionally, we should ensure that git worktree list --porcelain output is properly parsed to identify the main working tree, as Git natively reports it. This aligns with how the list command already handles the main repo (file:lib/commands/list.sh lines 44-47).
Implementation Steps
1. Enhance resolve_target() in file:lib/core.sh
Current Logic Flow:
flowchart TD
A[resolve_target called] --> B{identifier == '1'?}
B -->|Yes| C[Return main repo]
B -->|No| D{identifier == current branch in repo root?}
D -->|Yes| E[Return main repo]
D -->|No| F{Direct path exists?}
F -->|Yes| G[Return worktree path]
F -->|No| H{Search worktree dirs}
H -->|Found| I[Return worktree path]
H -->|Not found| J[Error: Worktree not found]
Loading
Modify the resolution logic (lines 274-310):
Verify the existing check at lines 274-279 is working correctly by ensuring get_current_branch("$repo_root") properly returns the branch checked out in the main repo
Consider using git worktree list --porcelain to get authoritative information about all worktrees including the main one
Add fallback logic after the worktree directory search (after line 300) to check if the identifier matches a branch in the main repo using git -C "$repo_root" rev-parse --verify "refs/heads/$identifier"
If the branch exists in the main repo and is checked out there, return the main repo path with is_main=1
Specific changes:
After line 279, add debug logging to verify the branch comparison is working
After line 300 (before the error at line 306), add a final check using git worktree list --porcelain to parse all worktrees including the main one
Parse the porcelain output to find entries where the branch matches the identifier
If found and the path matches the repo root, return 1\t$repo_root\t$identifier
2. Add comprehensive tests in file:tests/core_resolve_target.bats
Add test cases to verify the fix:
Test resolving a branch checked out in main repo when called from main repo
Test resolving a branch checked out in main repo when called from inside a linked worktree
Test resolving a branch checked out in main repo when called from outside the repo
Test that the fix doesn't break existing functionality for linked worktrees
Test edge cases like detached HEAD in main repo
Example test structure:
@test "resolve_target finds branch in main repo when not current"
@test "resolve_target finds main repo branch from inside worktree"
@test "resolve_target prefers linked worktree over main repo for same branch"
3. Update file:tests/cmd_go.bats and file:tests/cmd_ai.bats
Add integration tests:
Test cmd_go with a branch checked out in main repo
Test cmd_ai with a branch checked out in main repo
Verify error messages are clear when branch truly doesn't exist anywhere
4. Consider using git worktree list --porcelain for authoritative data
Alternative approach (more robust):
Instead of relying on directory scanning and get_current_branch(), parse git worktree list --porcelain output to get all worktrees including the main one. This is what Git itself reports and is the source of truth.
Implementation:
Create a helper function _parse_worktree_list() that parses git worktree list --porcelain
Returns a list of worktree entries with path, branch, and status
Use this in resolve_target() to find matching branches
This approach is more reliable than directory scanning and handles all edge cases
Porcelain format example:
worktree /Users/me/Code/my-repo
HEAD abc1234
branch refs/heads/my-feature-branch
worktree /Users/me/Code/my-repo-worktrees/other
HEAD def5678
branch refs/heads/other-branch
5. Update documentation if needed
Files to check:
file:README.md - Verify examples show that main repo branches can be referenced by name
file:CHANGELOG.md - Add entry for the fix in the Unreleased section
6. Verify related commands work correctly
Commands that use resolve_target() or resolve_worktree():
file:lib/commands/ai.sh (line 34)
file:lib/commands/go.sh (line 16)
file:lib/commands/run.sh (likely uses similar logic)
file:lib/commands/editor.sh (likely uses similar logic)
file:lib/commands/remove.sh (likely uses similar logic)
Ensure all these commands properly handle branches checked out in the main working tree after the fix.
Import In IDE
🤖 Prompt for AI Agents
## Observations
The issue occurs because `resolve_target()` in `file:lib/core.sh` (lines 258-310) doesn't properly recognize when a branch is checked out in the main working tree. While there is code at lines 274-279 that attempts to check if the identifier matches the current branch in the repo root, it appears this logic may not be working correctly or may have edge cases. The function only searches linked worktrees in the worktrees directory (lines 282-300) and doesn't fall back to checking if the branch exists in the main repo when no linked worktree matches.
## Approach
The fix involves enhancing the `resolve_target()` function to properly detect when a branch is checked out in the main working tree. The existing check at lines 274-279 should be verified and potentially improved to handle all edge cases. Additionally, we should ensure that `git worktree list --porcelain` output is properly parsed to identify the main working tree, as Git natively reports it. This aligns with how the `list` command already handles the main repo (file:lib/commands/list.sh lines 44-47).
## Implementation Steps### 1. Enhance `resolve_target()` in `file:lib/core.sh`**Current Logic Flow:**```mermaidflowchart TD A[resolve_target called] --> B{identifier == '1'?} B -->|Yes| C[Return main repo] B -->|No| D{identifier == current branch in repo root?} D -->|Yes| E[Return main repo] D -->|No| F{Direct path exists?} F -->|Yes| G[Return worktree path] F -->|No| H{Search worktree dirs} H -->|Found| I[Return worktree path] H -->|Not found| J[Error: Worktree not found]```**Modify the resolution logic (lines 274-310):**- Verify the existing check at lines 274-279 is working correctly by ensuring `get_current_branch("$repo_root")` properly returns the branch checked out in the main repo
- Consider using `git worktree list --porcelain` to get authoritative information about all worktrees including the main one
- Add fallback logic after the worktree directory search (after line 300) to check if the identifier matches a branch in the main repo using `git -C "$repo_root" rev-parse --verify "refs/heads/$identifier"`- If the branch exists in the main repo and is checked out there, return the main repo path with `is_main=1`**Specific changes:**- After line 279, add debug logging to verify the branch comparison is working
- After line 300 (before the error at line 306), add a final check using `git worktree list --porcelain` to parse all worktrees including the main one
- Parse the porcelain output to find entries where the branch matches the identifier
- If found and the path matches the repo root, return `1\t$repo_root\t$identifier`### 2. Add comprehensive tests in `file:tests/core_resolve_target.bats`**Add test cases to verify the fix:**- Test resolving a branch checked out in main repo when called from main repo
- Test resolving a branch checked out in main repo when called from inside a linked worktree
- Test resolving a branch checked out in main repo when called from outside the repo
- Test that the fix doesn't break existing functionality for linked worktrees
- Test edge cases like detached HEAD in main repo
**Example test structure:**```@test "resolve_target finds branch in main repo when not current"@test "resolve_target finds main repo branch from inside worktree"@test "resolve_target prefers linked worktree over main repo for same branch"```### 3. Update `file:tests/cmd_go.bats` and `file:tests/cmd_ai.bats`**Add integration tests:**- Test `cmd_go` with a branch checked out in main repo
- Test `cmd_ai` with a branch checked out in main repo
- Verify error messages are clear when branch truly doesn't exist anywhere
### 4. Consider using `git worktree list --porcelain` for authoritative data**Alternative approach (more robust):**
Instead of relying on directory scanning and `get_current_branch()`, parse `git worktree list --porcelain` output to get all worktrees including the main one. This is what Git itself reports and is the source of truth.
**Implementation:**- Create a helper function `_parse_worktree_list()` that parses `git worktree list --porcelain`- Returns a list of worktree entries with path, branch, and status
- Use this in `resolve_target()` to find matching branches
- This approach is more reliable than directory scanning and handles all edge cases
**Porcelain format example:**```worktree /Users/me/Code/my-repoHEAD abc1234branch refs/heads/my-feature-branchworktree /Users/me/Code/my-repo-worktrees/otherHEAD def5678branch refs/heads/other-branch```### 5. Update documentation if needed**Files to check:**-`file:README.md` - Verify examples show that main repo branches can be referenced by name
-`file:CHANGELOG.md` - Add entry for the fix in the Unreleased section
### 6. Verify related commands work correctly**Commands that use `resolve_target()` or `resolve_worktree()`:**-`file:lib/commands/ai.sh` (line 34)
-`file:lib/commands/go.sh` (line 16)
-`file:lib/commands/run.sh` (likely uses similar logic)
-`file:lib/commands/editor.sh` (likely uses similar logic)
-`file:lib/commands/remove.sh` (likely uses similar logic)
Ensure all these commands properly handle branches checked out in the main working tree after the fix.
This was fixed by #123/#126 which updated discover_repo_root() to use --git-common-dir instead of --show-toplevel. The existing fast-path check in resolve_target() (line 275-279) correctly resolves branches checked out in the main working tree — it just needed the correct repo_root value, which the older discover_repo_root() wasn't providing from inside linked worktrees.
The fix is on main but hasn't been released yet (post v2.3.0).
Activity
traycerai commentedon Feb 17, 2026
Plan
Observations
The issue occurs because
resolve_target()infile:lib/core.sh(lines 258-310) doesn't properly recognize when a branch is checked out in the main working tree. While there is code at lines 274-279 that attempts to check if the identifier matches the current branch in the repo root, it appears this logic may not be working correctly or may have edge cases. The function only searches linked worktrees in the worktrees directory (lines 282-300) and doesn't fall back to checking if the branch exists in the main repo when no linked worktree matches.Approach
The fix involves enhancing the
resolve_target()function to properly detect when a branch is checked out in the main working tree. The existing check at lines 274-279 should be verified and potentially improved to handle all edge cases. Additionally, we should ensure thatgit worktree list --porcelainoutput is properly parsed to identify the main working tree, as Git natively reports it. This aligns with how thelistcommand already handles the main repo (file:lib/commands/list.sh lines 44-47).Implementation Steps
1. Enhance
resolve_target()infile:lib/core.shCurrent Logic Flow:
flowchart TD A[resolve_target called] --> B{identifier == '1'?} B -->|Yes| C[Return main repo] B -->|No| D{identifier == current branch in repo root?} D -->|Yes| E[Return main repo] D -->|No| F{Direct path exists?} F -->|Yes| G[Return worktree path] F -->|No| H{Search worktree dirs} H -->|Found| I[Return worktree path] H -->|Not found| J[Error: Worktree not found]Modify the resolution logic (lines 274-310):
get_current_branch("$repo_root")properly returns the branch checked out in the main repogit worktree list --porcelainto get authoritative information about all worktrees including the main onegit -C "$repo_root" rev-parse --verify "refs/heads/$identifier"is_main=1Specific changes:
git worktree list --porcelainto parse all worktrees including the main one1\t$repo_root\t$identifier2. Add comprehensive tests in
file:tests/core_resolve_target.batsAdd test cases to verify the fix:
Example test structure:
3. Update
file:tests/cmd_go.batsandfile:tests/cmd_ai.batsAdd integration tests:
cmd_gowith a branch checked out in main repocmd_aiwith a branch checked out in main repo4. Consider using
git worktree list --porcelainfor authoritative dataAlternative approach (more robust):
Instead of relying on directory scanning and
get_current_branch(), parsegit worktree list --porcelainoutput to get all worktrees including the main one. This is what Git itself reports and is the source of truth.Implementation:
_parse_worktree_list()that parsesgit worktree list --porcelainresolve_target()to find matching branchesPorcelain format example:
5. Update documentation if needed
Files to check:
file:README.md- Verify examples show that main repo branches can be referenced by namefile:CHANGELOG.md- Add entry for the fix in the Unreleased section6. Verify related commands work correctly
Commands that use
resolve_target()orresolve_worktree():file:lib/commands/ai.sh(line 34)file:lib/commands/go.sh(line 16)file:lib/commands/run.sh(likely uses similar logic)file:lib/commands/editor.sh(likely uses similar logic)file:lib/commands/remove.sh(likely uses similar logic)Ensure all these commands properly handle branches checked out in the main working tree after the fix.
Import In IDE
🤖 Prompt for AI Agents
Execution Information
Branch: main
Commit: 57e7167
💡 Tips
Supported Commands (Inside Comments)
@traycerai generateto iterate on the previous version of the implementation plan.Supported Commands (Inside Description)
@traycerai ignoreanywhere in the ticket description to prevent this ticket from being processed.@traycerai branch:<branch-name>anywhere in the ticket description to specify the target branch for the implementation plan.Community
fix: resolve_target fallback via git worktree list (#127)
helizaga commentedon Feb 17, 2026
This was fixed by #123/#126 which updated
discover_repo_root()to use--git-common-dirinstead of--show-toplevel. The existing fast-path check inresolve_target()(line 275-279) correctly resolves branches checked out in the main working tree — it just needed the correctrepo_rootvalue, which the olderdiscover_repo_root()wasn't providing from inside linked worktrees.The fix is on
mainbut hasn't been released yet (post v2.3.0).