Skip to content

[Bug]: "Commit, push & PR" can't find the open PR when the only remote isn't named origin, and fails on gh pr create #15373

Closed

Description

@netherguy4

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

Single-repository workflow (no fork) where the only remote is not named origin:

  1. Clone a repo and name its only remote something else: git clone --origin fork https://github.com/<owner>/<repo>.git (or git remote rename origin fork).
  2. gh repo set-default <owner>/<repo> (the same repo fork points to).
  3. On branch dev (tracking fork/dev), commit and push, then open a PR dev → main in <owner>/<repo>. The first "Commit, push & PR" run does this fine.
  4. Commit again and run Commit, push & PR a second time while that PR is still open.

Expected behavior

The commit and push succeed, and the PR step finds the open PR and returns it (opened_existing), as it does when the remote is named origin.

Actual behavior

The commit and push succeed, but the action ends with:

Source control provider github failed in createChangeRequest: GitHub CLI command failed.

T3 Code calls gh pr create again, and gh refuses:

a pull request for branch "dev" into branch "main" already exists:
https://github.com/<owner>/<repo>/pull/3

Cause

Same root assumption as #7382 (the remote literally named origin is treated as the base repository), but a different failure: the existing-PR lookup rejects a same-repository PR.

In resolveBranchHeadContext (apps/server/src/git/GitManager.ts), resolveRemoteRepositoryContext(cwd, "origin") returns all nulls because there is no origin remote, so isCrossRepository falls through to the fallback branch:

const isCrossRepository =
  remoteRepository.repositoryNameWithOwner !== null && originRepository.repositoryNameWithOwner !== null
    ? /* compare */
    : remoteName !== null && remoteName !== "origin" && remoteRepository.repositoryNameWithOwner !== null;
//    ^ "fork" !== "origin" → true, although head and base are the same repository

findOpenPr then lists the PR correctly (gh pr list --head <owner>:dev / dev returns #3 with isCrossRepository: false), but matchesBranchHeadContext discards it:

if (headContext.isCrossRepository) {
  if (pr.isCrossRepository === false) return false;   // the real PR is dropped here
  ...
}

runPrStep concludes that no PR exists and goes on to createChangeRequest, which fails.

Renaming the remote to origin works around it: isCrossRepository becomes false, the selector is dev, and the PR matches.

Suggested fix

Don't infer the base repository from the remote name. Use what gh already resolved (gh repo set-default / remote.<name>.gh-resolved=base, or gh repo view --json nameWithOwner) as the target repository, and treat the head as cross-repository only when the head remote's nameWithOwner differs from it. The fallback remoteName !== "origin" heuristic produces a false positive whenever the only remote has a different name. This would also cover #7382.

Impact

Minor bug or occasional failure

Version or commit

0.0.45-nightly.20261002.2584

Environment

Linux (Fedora 44 / Bluefin), desktop AppImage, gh logged in via keyring

Activity

  1. juliusmarminge commented on Oct 3, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for tracing this so precisely, @netherguy4! This reproduces on current main (00eb8f6183). It's a real lookup bug and not a duplicate of #7382.

    What happens

    resolveBranchHeadContext in apps/server/src/git/GitManager.ts decides whether a branch is cross-repository by comparing its remote with the remote literally named origin. When there's no origin, that comparison can't run, and the fallback treats any other remote as a fork:

    remoteName !== null &&
      remoteName !== "origin" &&
      remoteRepository.repositoryNameWithOwner !== null

    So a same-repository checkout whose only remote is fork gets marked cross-repository. gh pr list --head dev returns the existing PR with isCrossRepository: false, but matchesBranchHeadContext drops it. runPrStep then falls through to gh pr create, which fails because the PR already exists. The first run still works because creation uses the owner-qualified head, which gh accepts for a same-repository PR. Renaming the remote to origin avoids the fallback, which matches your workaround.

    #7382 is the opposite mistake. There, origin is the fork, so the same comparison decides the branch isn't cross-repository and creation sends an unqualified head.

    Likely fix area

    • One option is to detect same-repository from the repository gh will target (gh repo set-default / remote.<name>.gh-resolved, or gh repo view --json nameWithOwner) instead of from the remote's name, as you suggested.
    • A narrower option is to drop the remoteName !== "origin" fallback when there's no origin to compare against.

    A maintainer will decide on the fix direction.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions