Skip to content

[pull] trunk from cli:trunk - #205

Merged
pull[bot] merged 27 commits into
arc675:trunkfrom
cli:trunk
Aug 4, 2026
Merged

[pull] trunk from cli:trunk#205
pull[bot] merged 27 commits into
arc675:trunkfrom
cli:trunk

Conversation

@pull

@pull pull Bot commented Aug 4, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

tidy-dev and others added 27 commits July 22, 2026 12:02
Support checking out a pull request into a new git worktree via
`gh pr checkout <pr> --worktree <path>`. Re-running against the same
path fast-forwards the existing worktree (idempotent, matching plain
checkout), and checking out a branch already present in another
worktree fails with a clear message. Adds a git.Client.Worktrees()
helper that parses `git worktree list --porcelain`.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
When --worktree is combined with --recurse-submodules, the submodule
sync/update commands ran in the main worktree instead of the newly
created one, leaving the worktree's submodules uninitialized. Prefix the
submodule commands with -C <path> (applied as cmd.Dir, mirroring the
fetch handling) so they operate on the correct worktree.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The missing-remote existing-worktree path used checkout -B <branch>
FETCH_HEAD, which unconditionally reset the branch and could discard
local commits even without --force. Switch to existence-aware logic that
mirrors the non-worktree paths: when the branch exists, check it out and
sync with merge --ff-only (or reset --hard under --force); only create
the branch from FETCH_HEAD when it does not exist yet.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The existing-remote worktree-reuse path assumed the target branch
already existed and ran checkout <branch>, which failed when a new
--branch name was supplied for an already-existing worktree (e.g.
repointing a review worktree at a different PR). Create the branch
tracking the remote when it does not exist yet, mirroring the
new-worktree path.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Use slices.Concat instead of append(prefix, ...) when building the
worktree-scoped submodule commands so the shared prefix slice can never
alias between the two commands. Add a unit test on authenticatedCommand
asserting the leading -C <path> is applied as cmd.Dir and stripped from
the args, which the CommandStubber-based tests cannot observe.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add the coverage gaps surfaced by review: re-running --detach against an
existing worktree (the per-worktree FETCH_HEAD path), a cmd.Dir
assertion for the worktree-local fetch shape (the real fork/detach
production combo, not just submodule), and a symlink-resolving
isWorktreeAtPath unit test so worktree reuse keeps working when git
reports a canonical path but the user passes a symlinked one. Drop the
custom-branch new-worktree case, which duplicated the new-branch path
already covered by the existing-worktree custom-branch case.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Restore the non-fast-forward // TODO breadcrumb in syncBranchCmds
- Early-return the non-worktree case in detachCmds to reduce nesting
- Reject a --worktree target that is a leaf symlink or non-directory
  via ensureWorktreePathSafe, with unit coverage

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Replace isWorktreeAtPath path-matching with git rev-parse
  --show-prefix --git-common-dir, letting git resolve symlinks, "..",
  case, and trailing slashes; delete resolvePath/EvalSymlinks
- Reject a --worktree target that resolves to the current worktree,
  which would otherwise silently switch the current tree's branch and
  print a nonsensical "cd ." hint

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
isCurrentWorktree resolves the target with filepath.Abs, which yields a
drive-letter path on Windows (e.g. D:\path\to\wt). Match the -C target
via a wildcard so the show-toplevel stub matches on all platforms.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Collapse the separate worktree-detection helpers (isWorktreeAtPath,
isCurrentWorktree, worktreeToplevel, worktreeInfoAtPath, repoCommonDir)
into a single resolveWorktreeTarget call made once in checkoutRun. It runs
two rev-parse queries (current + target) instead of the previous four and
hands the command builders a plain reuseWorktree bool, so they no longer
depend on the git client for detection and stay pure.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Streamline comments in the worktree checkout path to only the non-obvious
rationale, and rename the worktreeTarget fields to isCurrentWorktree and
isExistingWorktree so they read clearly without explanation.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Match the surrounding codebase, which rarely documents unexported helpers:
remove the godoc on worktreeCheckoutCmds and tighten syncBranchCmds, keeping
comments only where the rationale is non-obvious.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
resolveWorktreeTarget deliberately proceeds with default flags when a
rev-parse fails, which the nilerr linter flagged as returning a nil error
after a non-nil one. Have revParseFacts report success via an ok bool
instead so the best-effort fallthrough is explicit and lint-clean.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Reword the --worktree rejection to avoid the "current worktree" jargon,
which is confusing for users who don't think of their main checkout as a
worktree. Point at "the repository you're already in" instead.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Reject --worktree paths that point inside a different repository or nest
inside an existing worktree with clear messages, instead of deferring to
git (which silently creates a nested worktree or emits a generic error).

Fold all rejection cases into resolveWorktreeTarget, which now returns
(reuseWorktree bool, error), removing the worktreeTarget struct and
simplifying the checkoutRun guard.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Cover checking out a PR into a new git worktree, reusing an existing
worktree, detached checkouts, checkouts of fork PRs whose head repo is
not a configured remote, and force syncing across diverging branches.
Each scenario also asserts the main working copy's branch is untouched.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e4cb568-27f3-4c7e-a344-859e2c2d69b0
Signed-off-by: Babak K. Shandiz <babakks@github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e4cb568-27f3-4c7e-a344-859e2c2d69b0
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e4cb568-27f3-4c7e-a344-859e2c2d69b0
git worktree add treats a path that starts with a hyphen as an option,
so a --worktree value like -foo failed with an unknown-switch error.
Pass a -- end-of-options separator before the path in every worktree add
invocation so the value is always parsed positionally.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 6e4cb568-27f3-4c7e-a344-859e2c2d69b0
The checkoutRun test stubs hardcoded `git -C /path/to/wt rev-parse`, but the
command runs after filepath.Abs, which yields `D:\path\to\wt` on Windows and
left the stub unmatched (panic: no exec stub). Use a separator-agnostic
`.+path.to.wt` pattern so the stub matches the absolute path on every platform
while still asserting the -C directory.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@pull pull Bot locked and limited conversation to collaborators Aug 4, 2026
@pull pull Bot added the ⤵️ pull label Aug 4, 2026
@pull
pull Bot merged commit 8f7afbd into arc675:trunk Aug 4, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants