Skip to content

fix: Reuse issue branches, isolate tests from the repo - #114

Merged
chmouel merged 5 commits into
mainfrom
lwci-shoudl-work
Oct 28, 2026
Merged

chmouel merged 5 commits into
mainfrom
lwci-shoudl-work

Conversation

@chmouel

@chmouel chmouel commented Oct 28, 2026 •

Copy link
Copy Markdown
Owner

Two fixes found while creating a worktree from an issue.

Creating from an issue fails when its branch already exists

lazyworktree create -I (and --from-issue) stopped with fatal: a branch named 'issue-397-...' already exists whenever a branch for that issue was left over from an earlier worktree. --no-workspace failed the same way.

The existing branch is now reused, matching what --from-pr already does:

flowchart LR
    A[issue branch exists?] -- no --> B[create branch from base, new worktree]
    A -- yes --> C{checked out in a worktree?}
    C -- yes --> D[return that worktree's path]
    C -- no --> E[new worktree on the existing branch]
Loading

Running the same command twice now returns the existing worktree, with or without -U. If the worktree holding the branch was deleted outside git, the command says so and suggests git worktree prune rather than returning a path that no longer exists.

With --no-workspace, it switches to the existing branch instead of creating it. If another worktree already holds the branch, the error names that worktree. The CLI docs and man page describe the new behaviour.

Tests wrote into the developer's repository from git hooks

The go test ./... pre-commit/pre-push hook, run inside a linked worktree, corrupted the real repository. Git gives hooks an absolute GIT_DIR in that case, and the tests that build scratch repos inherited it. In one push it turned the repo bare, set user.name/user.email to test values, added an upstream remote, created feature* branches, committed on top of main and the current branch, and wrote commit.gpgsign=false. That last setting had turned off commit signing in this repo since March.

Every package whose tests run git now clears git's repository variables (the git rev-parse --local-env-vars list) in TestMain, through a small internal/testenv helper. The Herdr tests that landed on main while this PR was open did the same damage again, so the hook now clears those variables before running go test as well. A package that forgets the TestMain is still covered. A regression test in internal/testenv points GIT_DIR at a scratch linked worktree and checks that the repository stays untouched.

To reproduce, create a scratch repo with a linked worktree and run GIT_DIR=<that worktree's gitdir> go test ./.... Before this change the scratch repo picks up the branches, identity and core.bare=true. After it, nothing changes.

@chmouel chmouel added the bug Something isn't working label Oct 28, 2026
Copilot AI balanced review requested due to automatic review settings October 28, 2026 14:19
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (2) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Repeated issue creation still fails ✓ Resolved
Description
CreateFromIssueWithFS checks whether the target directory exists before reaching the new lookup
for a worktree already using the issue branch. When the first creation used the generated target
path, a second create --from-issue returns path already exists under the default settings
instead of returning that worktree.
Code

internal/cli/operations.go[R757-758]

+	if branchExists {
+		worktrees, err := gitSvc.GetWorktrees(ctx)
Evidence
The target-path check exits on an existing directory at lines 747–753, while the newly added branch
lookup starts at line 757. The CLI sets UpdateOnExisting from an opt-in flag, and the analogous PR
workflow performs its attached-worktree lookup before checking the target path.

internal/cli/operations.go[740-766]
internal/bootstrap/commands.go[589-594]
internal/cli/operations.go[600-620]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A repeated issue creation fails because the target-path conflict check returns before the new attached-worktree lookup.
## Fix Focus Areas
- internal/cli/operations.go[747-766]
## Recommended Fix
For an existing issue branch, look up its attached worktree before checking whether the generated target path exists. Return the attached worktree's actual path; retain the path-conflict check when a new worktree must be created.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Repeated issue creation still fails ✓ Resolved
Description
CreateFromIssueWithFS checks whether the target directory exists before reaching the new lookup
for a worktree already using the issue branch. When the first creation used the generated target
path, a second create --from-issue returns path already exists under the default settings
instead of returning that worktree.
Code

internal/cli/operations.go[R757-758]

+	if branchExists {
+		worktrees, err := gitSvc.GetWorktrees(ctx)
Evidence
The target-path check exits on an existing directory at lines 747–753, while the newly added branch
lookup starts at line 757. The CLI sets UpdateOnExisting from an opt-in flag, and the analogous PR
workflow performs its attached-worktree lookup before checking the target path.

internal/cli/operations.go[740-766]
internal/bootstrap/commands.go[589-594]
internal/cli/operations.go[600-620]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A repeated issue creation fails because the target-path conflict check returns before the new attached-worktree lookup.
## Fix Focus Areas
- internal/cli/operations.go[747-766]
## Recommended Fix
For an existing issue branch, look up its attached worktree before checking whether the generated target path exists. Return the attached worktree's actual path; retain the path-conflict check when a new worktree must be created.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Repeated issue creation still fails ✓ Resolved
Description
CreateFromIssueWithFS checks whether the target directory exists before reaching the new lookup
for a worktree already using the issue branch. When the first creation used the generated target
path, a second create --from-issue returns path already exists under the default settings
instead of returning that worktree.
Code

internal/cli/operations.go[R757-758]

+	if branchExists {
+		worktrees, err := gitSvc.GetWorktrees(ctx)
Evidence
The target-path check exits on an existing directory at lines 747–753, while the newly added branch
lookup starts at line 757. The CLI sets UpdateOnExisting from an opt-in flag, and the analogous PR
workflow performs its attached-worktree lookup before checking the target path.

internal/cli/operations.go[740-766]
internal/bootstrap/commands.go[589-594]
internal/cli/operations.go[600-620]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A repeated issue creation fails because the target-path conflict check returns before the new attached-worktree lookup.
## Fix Focus Areas
- internal/cli/operations.go[747-766]
## Recommended Fix
For an existing issue branch, look up its attached worktree before checking whether the generated target path exists. Return the attached worktree's actual path; retain the path-conflict check when a new worktree must be created.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Worktree docs omit issue branch reuse 📘 Rule violation § Compliance
Description
CreateFromIssueWithFS now reuses an existing local issue branch, returns its attached worktree
path when present, and switches to that branch with --no-workspace. The changed `create
--from-issue behavior is absent from docs/core/worktree-operations.md`,
docs/worktree-lifecycle.md, README.md, and the internal help template, leaving those
descriptions of issue-based creation incomplete.
Code

internal/cli/operations.go[R714-718]

branchName := utils.GenerateIssueWorktreeName(selectedIssue, template, "")
+	branchExists := localBranchExists(ctx, gitSvc, branchName)
if noWorkspace {
-		if !gitSvc.RunCommandChecked(
+		if !branchExists && !gitSvc.RunCommandChecked(
Evidence
The existing-branch path in internal/cli/operations.go changes issue-based creation behavior, but
the two required lifecycle and operations documents remain unchanged and do not describe branch
reuse. The README and internal help template are also unchanged and provide no corresponding
explanation; only the command-specific documentation was updated.

Rule 349607: Update both worktree documentation files when changing worktree operations
Rule 349624: Update README for any user-facing behavior change
Rule 349605: Keep CLI help template in sync with command/flag changes
Rule 349615: Update internal help template for any user‑facing change
internal/cli/operations.go[714-718]
docs/cli/create.md[54-57]
docs/core/worktree-operations.md[1-15]
docs/worktree-lifecycle.md[1-18]
internal/cli/operations.go[756-772]
README.md[10-25]
internal/app/screen/help.go[50-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Document the changed issue-based creation behavior across the operations and lifecycle guides, README, and internal help: existing local issue branches are reused, an attached worktree path is returned when present, and `--no-workspace` switches to the existing branch.
## Fix Focus Areas
- docs/core/worktree-operations.md[1-151]
- docs/worktree-lifecycle.md[1-98]
- README.md[1-112]
- internal/app/screen/help.go[50-60]
- internal/cli/operations.go[756-772]
## Recommended Fix
Update both documentation files consistently with the implementation and the existing `docs/cli/create.md` and `lazyworktree.1` descriptions. Add a concise usage or behavior note to the README and describe issue-creation reuse in the relevant internal help content, using the current option names and semantics.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Issue branch switching fails across worktrees ✓ Resolved
Description
CreateFromIssueWithFS skips branch creation when an issue branch exists, then calls git switch
without checking whether another worktree has it checked out. With --no-workspace, that
attached-branch state makes the switch fail, whereas the new worktree-mode path detects the
attachment and returns its path.
Code

internal/cli/operations.go[718]

+		if !branchExists && !gitSvc.RunCommandChecked(
Evidence
The new existence condition at line 718 bypasses git branch, but the following git switch
remains unconditional. The worktree-mode path explicitly identifies attached branches; the existing
PR branch-switching implementation also checks for attachment before switching.

internal/cli/operations.go[715-732]
internal/cli/operations.go[756-766]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
No-workspace issue creation attempts to switch to an existing branch even when another worktree has it checked out.
## Fix Focus Areas
- internal/cli/operations.go[715-732]
- internal/cli/operations.go[756-766]
## Recommended Fix
Check whether an existing branch is attached before calling `git switch`. Handle that state explicitly, either by returning a compatible existing-worktree result or by giving a clear error directing the user to that worktree; add a no-workspace test for it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Worktree docs omit issue branch reuse 📘 Rule violation § Compliance
Description
CreateFromIssueWithFS now reuses an existing local issue branch, returns its attached worktree
path when present, and switches to that branch with --no-workspace. The changed `create
--from-issue behavior is absent from docs/core/worktree-operations.md`,
docs/worktree-lifecycle.md, README.md, and the internal help template, leaving those
descriptions of issue-based creation incomplete.
Code

internal/cli/operations.go[R714-718]

branchName := utils.GenerateIssueWorktreeName(selectedIssue, template, "")
+	branchExists := localBranchExists(ctx, gitSvc, branchName)
if noWorkspace {
-		if !gitSvc.RunCommandChecked(
+		if !branchExists && !gitSvc.RunCommandChecked(
Evidence
The existing-branch path in internal/cli/operations.go changes issue-based creation behavior, but
the two required lifecycle and operations documents remain unchanged and do not describe branch
reuse. The README and internal help template are also unchanged and provide no corresponding
explanation; only the command-specific documentation was updated.

Rule 349607: Update both worktree documentation files when changing worktree operations
Rule 349624: Update README for any user-facing behavior change
Rule 349605: Keep CLI help template in sync with command/flag changes
Rule 349615: Update internal help template for any user‑facing change
internal/cli/operations.go[714-718]
docs/cli/create.md[54-57]
docs/core/worktree-operations.md[1-15]
docs/worktree-lifecycle.md[1-18]
internal/cli/operations.go[756-772]
README.md[10-25]
internal/app/screen/help.go[50-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Document the changed issue-based creation behavior across the operations and lifecycle guides, README, and internal help: existing local issue branches are reused, an attached worktree path is returned when present, and `--no-workspace` switches to the existing branch.
## Fix Focus Areas
- docs/core/worktree-operations.md[1-151]
- docs/worktree-lifecycle.md[1-98]
- README.md[1-112]
- internal/app/screen/help.go[50-60]
- internal/cli/operations.go[756-772]
## Recommended Fix
Update both documentation files consistently with the implementation and the existing `docs/cli/create.md` and `lazyworktree.1` descriptions. Add a concise usage or behavior note to the README and describe issue-creation reuse in the relevant internal help content, using the current option names and semantics.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (3)
7. Issue branch switching fails across worktrees ✓ Resolved
Description
CreateFromIssueWithFS skips branch creation when an issue branch exists, then calls git switch
without checking whether another worktree has it checked out. With --no-workspace, that
attached-branch state makes the switch fail, whereas the new worktree-mode path detects the
attachment and returns its path.
Code

internal/cli/operations.go[718]

+		if !branchExists && !gitSvc.RunCommandChecked(
Evidence
The new existence condition at line 718 bypasses git branch, but the following git switch
remains unconditional. The worktree-mode path explicitly identifies attached branches; the existing
PR branch-switching implementation also checks for attachment before switching.

internal/cli/operations.go[715-732]
internal/cli/operations.go[756-766]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
No-workspace issue creation attempts to switch to an existing branch even when another worktree has it checked out.
## Fix Focus Areas
- internal/cli/operations.go[715-732]
- internal/cli/operations.go[756-766]
## Recommended Fix
Check whether an existing branch is attached before calling `git switch`. Handle that state explicitly, either by returning a compatible existing-worktree result or by giving a clear error directing the user to that worktree; add a no-workspace test for it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Worktree docs omit issue branch reuse ✗ Dismissed
Description
CreateFromIssueWithFS now reuses an existing local issue branch, returns its attached worktree
path when present, and switches to that branch with --no-workspace. The changed `create
--from-issue behavior is absent from docs/core/worktree-operations.md`,
docs/worktree-lifecycle.md, README.md, and the internal help template, leaving those
descriptions of issue-based creation incomplete.
Code

internal/cli/operations.go[R714-718]

  branchName := utils.GenerateIssueWorktreeName(selectedIssue, template, "")
+	branchExists := localBranchExists(ctx, gitSvc, branchName)

  if noWorkspace {
-		if !gitSvc.RunCommandChecked(
+		if !branchExists && !gitSvc.RunCommandChecked(
Evidence
The existing-branch path in internal/cli/operations.go changes issue-based creation behavior, but
the two required lifecycle and operations documents remain unchanged and do not describe branch
reuse. The README and internal help template are also unchanged and provide no corresponding
explanation; only the command-specific documentation was updated.

Rule 349607: Update both worktree documentation files when changing worktree operations
Rule 349624: Update README for any user-facing behavior change
Rule 349605: Keep CLI help template in sync with command/flag changes
Rule 349615: Update internal help template for any user‑facing change
internal/cli/operations.go[714-718]
docs/cli/create.md[54-57]
docs/core/worktree-operations.md[1-15]
docs/worktree-lifecycle.md[1-18]
internal/cli/operations.go[756-772]
README.md[10-25]
internal/app/screen/help.go[50-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Document the changed issue-based creation behavior across the operations and lifecycle guides, README, and internal help: existing local issue branches are reused, an attached worktree path is returned when present, and `--no-workspace` switches to the existing branch.
## Fix Focus Areas
- docs/core/worktree-operations.md[1-151]
- docs/worktree-lifecycle.md[1-98]
- README.md[1-112]
- internal/app/screen/help.go[50-60]
- internal/cli/operations.go[756-772]
## Recommended Fix
Update both documentation files consistently with the implementation and the existing `docs/cli/create.md` and `lazyworktree.1` descriptions. Add a concise usage or behavior note to the README and describe issue-creation reuse in the relevant internal help content, using the current option names and semantics.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. Issue branch switching fails across worktrees ✓ Resolved
Description
CreateFromIssueWithFS skips branch creation when an issue branch exists, then calls git switch
without checking whether another worktree has it checked out. With --no-workspace, that
attached-branch state makes the switch fail, whereas the new worktree-mode path detects the
attachment and returns its path.
Code

internal/cli/operations.go[718]

+		if !branchExists && !gitSvc.RunCommandChecked(
Evidence
The new existence condition at line 718 bypasses git branch, but the following git switch
remains unconditional. The worktree-mode path explicitly identifies attached branches; the existing
PR branch-switching implementation also checks for attachment before switching.

internal/cli/operations.go[715-732]
internal/cli/operations.go[756-766]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
No-workspace issue creation attempts to switch to an existing branch even when another worktree has it checked out.
## Fix Focus Areas
- internal/cli/operations.go[715-732]
- internal/cli/operations.go[756-766]
## Recommended Fix
Check whether an existing branch is attached before calling `git switch`. Handle that state explicitly, either by returning a compatible existing-worktree result or by giving a clear error directing the user to that worktree; add a no-workspace test for it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@qodo-code-review

qodo-code-review Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

PR Summary by Qodo

Reuse issue branches and isolate Git tests from hook environments

🐞 Bug fix 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Reuse existing issue branches or return their worktree paths instead of failing on creation.
• Clear inherited repository-scoped Git variables before tests run, protecting the caller's
 repository.
• Document issue-branch reuse and cover its worktree and no-workspace paths.
Diagram

graph TD
  I["Issue create"] --> B{"Branch exists?"} -->|yes| A{"Already attached?"} -->|yes| R["Return path"]
  H["Hook-launched tests"] --> C["TestMain cleanup"] --> S["Scratch repository"]
  B -->|no| W["Create or switch"]
  A -->|no| W
Loading
High-Level Assessment

Reuse the existing branch and worktree lookup helpers for issue creation, and clear Git's repository-scoped variables once at each affected package's TestMain entry point. Resetting an existing branch from the base could discard its commits; scrubbing individual Git commands would leave more opportunities to miss a test path.

Files changed (12) +202 / -4

Bug fix (1) +21 / -3
operations.goReuse existing branches in issue creation +21/-3

Reuse existing branches in issue creation

• Checks whether the generated issue branch exists before creating it. No-workspace mode switches to an existing branch; worktree mode returns its attached path or adds a worktree using its existing commits.

internal/cli/operations.go

Tests (8) +174 / -0
main_test.goClear Git repository variables before app tests +12/-0

Clear Git repository variables before app tests

• Adds a TestMain that invokes the shared Git environment cleanup before running app tests.

internal/app/main_test.go

main_test.goClear Git repository variables before service tests +12/-0

Clear Git repository variables before service tests

• Adds a TestMain that invokes the shared Git environment cleanup before running service tests.

internal/app/services/main_test.go

main_test.goClear Git repository variables before bootstrap tests +12/-0

Clear Git repository variables before bootstrap tests

• Adds a TestMain that invokes the shared Git environment cleanup before running bootstrap tests.

internal/bootstrap/main_test.go

main_test.goClear Git repository variables before CLI tests +12/-0

Clear Git repository variables before CLI tests

• Adds a TestMain that invokes the shared Git environment cleanup before running CLI tests.

internal/cli/main_test.go

operations_flow_test.goCover existing issue-branch paths +69/-0

Cover existing issue-branch paths

• Adds table-driven tests for an unattached branch, a branch attached elsewhere, and no-workspace mode. Verifies the returned value and Git commands for each case.

internal/cli/operations_flow_test.go

main_test.goClear Git repository variables before config tests +12/-0

Clear Git repository variables before config tests

• Adds a TestMain that invokes the shared Git environment cleanup before running config tests.

internal/config/main_test.go

main_test.goClear Git repository variables before Git tests +12/-0

Clear Git repository variables before Git tests

• Adds a TestMain that invokes the shared Git environment cleanup before running Git package tests.

internal/git/main_test.go

testenv.goCentralize Git repository environment cleanup +33/-0

Centralize Git repository environment cleanup

• Introduces a test helper that unsets the repository-scoped variables listed by git rev-parse --local-env-vars. This prevents tests launched from Git hooks from directing scratch-repository commands at the caller's repository.

internal/testenv/testenv.go

Documentation (3) +7 / -1
create.mdDocument issue-branch reuse +5/-0

Document issue-branch reuse

• Explains how issue branch names are generated and that an existing local branch is reused. Notes that an already-attached branch returns its worktree path.

docs/cli/create.md

architecture.mdDescribe the test environment helper +1/-0

Describe the test environment helper

• Adds internal/testenv to the architecture reference and explains its role in protecting repositories from Git variables inherited by hook-launched tests.

docs/development/architecture.md

lazyworktree.1Document issue-branch reuse in the man page +1/-1

Document issue-branch reuse in the man page

• Clarifies that --from-issue reuses a local branch when present and returns the path of a worktree where it is already checked out.

lazyworktree.1

@qodo-code-review

qodo-code-review Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Repeated issue creation still fails ✓ Resolved
Description
CreateFromIssueWithFS checks whether the target directory exists before reaching the new lookup
for a worktree already using the issue branch. When the first creation used the generated target
path, a second create --from-issue returns path already exists under the default settings
instead of returning that worktree.
Code

internal/cli/operations.go[R757-758]

+	if branchExists {
+		worktrees, err := gitSvc.GetWorktrees(ctx)
Evidence
The target-path check exits on an existing directory at lines 747–753, while the newly added branch
lookup starts at line 757. The CLI sets UpdateOnExisting from an opt-in flag, and the analogous PR
workflow performs its attached-worktree lookup before checking the target path.

internal/cli/operations.go[740-766]
internal/bootstrap/commands.go[589-594]
internal/cli/operations.go[600-620]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A repeated issue creation fails because the target-path conflict check returns before the new attached-worktree lookup.
## Fix Focus Areas
- internal/cli/operations.go[747-766]
## Recommended Fix
For an existing issue branch, look up its attached worktree before checking whether the generated target path exists. Return the attached worktree's actual path; retain the path-conflict check when a new worktree must be created.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Worktree docs omit issue branch reuse ✗ Dismissed
Description
CreateFromIssueWithFS now reuses an existing local issue branch, returns its attached worktree
path when present, and switches to that branch with --no-workspace. The changed `create
--from-issue behavior is absent from docs/core/worktree-operations.md`,
docs/worktree-lifecycle.md, README.md, and the internal help template, leaving those
descriptions of issue-based creation incomplete.
Code

internal/cli/operations.go[R714-718]

	branchName := utils.GenerateIssueWorktreeName(selectedIssue, template, "")
+	branchExists := localBranchExists(ctx, gitSvc, branchName)

	if noWorkspace {
-		if !gitSvc.RunCommandChecked(
+		if !branchExists && !gitSvc.RunCommandChecked(
Evidence
The existing-branch path in internal/cli/operations.go changes issue-based creation behavior, but
the two required lifecycle and operations documents remain unchanged and do not describe branch
reuse. The README and internal help template are also unchanged and provide no corresponding
explanation; only the command-specific documentation was updated.

Rule 349607: Update both worktree documentation files when changing worktree operations
Rule 349624: Update README for any user-facing behavior change
Rule 349605: Keep CLI help template in sync with command/flag changes
Rule 349615: Update internal help template for any user‑facing change
internal/cli/operations.go[714-718]
docs/cli/create.md[54-57]
docs/core/worktree-operations.md[1-15]
docs/worktree-lifecycle.md[1-18]
internal/cli/operations.go[756-772]
README.md[10-25]
internal/app/screen/help.go[50-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Document the changed issue-based creation behavior across the operations and lifecycle guides, README, and internal help: existing local issue branches are reused, an attached worktree path is returned when present, and `--no-workspace` switches to the existing branch.

## Fix Focus Areas
- docs/core/worktree-operations.md[1-151]
- docs/worktree-lifecycle.md[1-98]
- README.md[1-112]
- internal/app/screen/help.go[50-60]
- internal/cli/operations.go[756-772]

## Recommended Fix
Update both documentation files consistently with the implementation and the existing `docs/cli/create.md` and `lazyworktree.1` descriptions. Add a concise usage or behavior note to the README and describe issue-creation reuse in the relevant internal help content, using the current option names and semantics.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Issue branch switching fails across worktrees ✓ Resolved
Description
CreateFromIssueWithFS skips branch creation when an issue branch exists, then calls git switch
without checking whether another worktree has it checked out. With --no-workspace, that
attached-branch state makes the switch fail, whereas the new worktree-mode path detects the
attachment and returns its path.
Code

internal/cli/operations.go[718]

+		if !branchExists && !gitSvc.RunCommandChecked(
Evidence
The new existence condition at line 718 bypasses git branch, but the following git switch
remains unconditional. The worktree-mode path explicitly identifies attached branches; the existing
PR branch-switching implementation also checks for attachment before switching.

internal/cli/operations.go[715-732]
internal/cli/operations.go[756-766]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
No-workspace issue creation attempts to switch to an existing branch even when another worktree has it checked out.
## Fix Focus Areas
- internal/cli/operations.go[715-732]
- internal/cli/operations.go[756-766]
## Recommended Fix
Check whether an existing branch is attached before calling `git switch`. Handle that state explicitly, either by returning a compatible existing-worktree result or by giving a clear error directing the user to that worktree; add a no-workspace test for it.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 29 rules
Review mode: Auto: ⚖️ Balanced: Runtime git behavior and test isolation create meaningful, localized risk.

Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread internal/cli/operations.go Resolved
Comment thread internal/cli/operations.go Resolved
Comment thread internal/cli/operations.go Resolved

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Issue-worktree reuse can fail on path conflicts or a detached HEAD, return deleted directories, and lacks a regression test for inherited Git environment isolation.

4 open issues
What changed in this PR

This PR adds issue-branch reuse to worktree creation and isolates Git-running tests from repository environment variables inherited through hooks.

Changes:

  • Reuses existing issue branches when creating worktrees or switching with --no-workspace.
  • Adds shared Git-environment cleanup through package-level TestMain functions.
  • Adds branch-reuse tests and documents the new behaviour and test helper.

Tests were not run because project test execution is unavailable in this review environment.

File Description
lazyworktree.1 Documents existing issue-branch reuse.
internal/​testenv/​testenv.go Adds shared cleanup of Git repository environment variables.
internal/​git/​main_test.go Applies environment cleanup before Git tests.
internal/​config/​main_test.go Applies environment cleanup before configuration tests.
internal/​cli/​operations.go Adds existing issue-branch and worktree reuse paths.
internal/​cli/​operations_flow_test.go Tests branch reuse, attached worktrees, and branch switching.
internal/​cli/​main_test.go Applies environment cleanup before CLI tests.
internal/​bootstrap/​main_test.go Applies environment cleanup before bootstrap tests.
internal/​app/​services/​main_test.go Applies environment cleanup before application service tests.
internal/​app/​main_test.go Applies environment cleanup before application tests.
docs/​development/​architecture.md Describes the test-environment helper’s purpose.
docs/​cli/​create.md Documents issue-specific branch reuse behaviour.

Review effort: Balanced

Comment thread internal/cli/operations.go Resolved
Comment thread internal/cli/operations.go Resolved
Comment thread internal/cli/operations.go Resolved
Comment thread internal/testenv/testenv.go Resolved
Creating a worktree from an issue on the command line (for example
with "lazyworktree create -I") stopped with a "branch already exists"
error whenever a branch for that issue was left over from earlier
work. This happens when a previous worktree for the issue was removed
but its branch was kept. The same problem also hit the
"--no-workspace" mode.

Lazyworktree now picks up the existing branch and keeps going. If that
branch is already open in another worktree, it hands back the path of
that worktree, which is what already happens for pull requests.
Otherwise it opens a new worktree on the branch with its existing
commits. In "--no-workspace" mode it switches to the branch. The
command reference and the manual page now describe this.
Running the test suite from a git hook inside a linked worktree wrote
into the developer's own repository. Git hands its hooks the location
of the repository it is working on, and in a worktree that location is
a full path. The tests that build throwaway repositories inherited it,
so their commits, branches, remotes and settings landed in the real
repository instead. It also turned the repository into a bare one, set
a fake author name and email, and switched off commit signing.

Every package whose tests run git now clears those inherited
repository settings before any test starts, so each test only ever
touches its own temporary repository. The architecture notes list the
new test helper.
Running the issue create command twice for the same issue used to stop
with "path already exists" unless the -U flag was given, even though
the worktree it wanted was already there. It now hands back that
worktree straight away.

With --no-workspace, switching to an issue branch that another worktree
already holds failed with a raw git error. The message now says which
worktree has the branch, so it is clear where to go instead.

The docs explain both cases.
If the worktree holding an issue branch had been deleted outside git,
the create command still handed back its old path, which no longer
existed. It now says the worktree is gone and suggests running
"git worktree prune" first.

A new test makes sure tests run from a git hook in a linked worktree
cannot change the real repository again, so the earlier fix cannot
quietly break.
The Herdr tests that just arrived from main create git repositories,
and their package had not been protected yet. Running them from the
push hook in a worktree added test commits and branches to the real
repository again and marked it as bare.

Those tests are now protected too. The push hook also clears git's
repository settings before running the tests, so a package added later
cannot repeat this, even if it forgets the protection.
@chmouel
chmouel merged commit 9afce92 into main Oct 28, 2026
2 checks passed
@chmouel
chmouel deleted the lwci-shoudl-work branch October 28, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants