Skip to content

2.66.0 regression: gh pr create doesn't work any more with triangular workflows #10346

Closed

Description

@neutrinoceros

Describe the bug

gh pr create appears to always crash on a local repo with more than one remote. Specifically, an error is raised when checking for an existing PR. This happens regardless if already pushed my branch to one of the remotes or not.

$ gh pr create  
? Where should we push the 'dep/bump_matplotlib_3.6.0' branch? <origin>
error checking for existing pull request: no remote for "neutrinoceros:<branch_name>@{push}" found in "upstream, origin"
$ git push --set-upstream origin <branch_name>
$ gh pr create                                           
error checking for existing pull request: no remote for "neutrinoceros:<branch_name>@{push}" found in "upstream, origin"

Affected version

This is a regression in 2.66.0 . 2.65.0 worked fine for me.

Steps to reproduce the behavior

$ git clone [email protected]:neutrinoceros/cli.git
$ cd cli
$ git remote add upstream https://github.com/cli/cli
$ git switch -c testbranch
$ echo "hello world" > testfile.txt
$ git add testfile.txt
$ git commit -am "test commit"
$ gh repo set-default
<cli/cli>
$ gh pr create
? Where should we push the 'testbranch' branch? neutrinoceros/cli
error checking for existing pull request: no remote for "neutrinoceros:testbranch@{push}" found in "upstream, origin"

Expected vs actual behavior

gh pr create should still work in a triangular workflow

Logs

$ GH_DEBUG=true gh pr create
[git remote -v]
[git config --get-regexp ^remote\..*\.gh-resolved$]
* Request at 2025-01-31 10:53:57.39598 +0100 CET m=+0.125380751
* Request to https://api.github.com/graphql
* Request took 389.563792ms
[git symbolic-ref --quiet HEAD]
[git status --porcelain]
[git config --get-regexp ^branch\.testbranch\.(remote|merge|pushremote|gh-merge-base)$]
[git show-ref --verify -- HEAD refs/remotes/upstream/testbranch refs/remotes/origin/testbranch]
* Request at 2025-01-31 10:53:57.858646 +0100 CET m=+0.588045959
* Request to https://api.github.com/graphql
* Request took 348.268709ms
* Request at 2025-01-31 10:53:58.241026 +0100 CET m=+0.970424584
* Request to https://api.github.com/graphql
* Request took 203.035125ms
? Where should we push the 'testbranch' branch? neutrinoceros/cli
[git -c log.ShowSignature=false log --pretty=format:%H%x00%s%x00%b%x00 --cherry upstream/trunk...testbranch]
[git remote -v]
[git config --get-regexp ^remote\..*\.gh-resolved$]
[git config --get-regexp ^branch\.neutrinoceros:testbranch\.(remote|merge|pushremote|gh-merge-base)$]
[git remote -v]
⣾[git config --get-regexp ^remote\..*\.gh-resolved$]
[git config push.default]
[git rev-parse --abbrev-ref neutrinoceros:testbranch@{push}]
[git config remote.pushDefault]
error checking for existing pull request: no remote for "neutrinoceros:testbranch@{push}" found in "upstream, origin"

Activity

  1. andyfeller commented on Jan 31, 2025

    @andyfeller
    Contributor

    Thank you for raising this issue up, @neutrinoceros! 🙇 Let me see about digging into this and working with the other maintainers regarding the changes from #9208.

  2. added
    coreThis issue is not accepting PRs from outside contributors
    priority-2Affects more than a few users but doesn't prevent core functions
    on Jan 31, 2025
  3. andyfeller commented on Jan 31, 2025

    @andyfeller
    Contributor

    @neutrinoceros : Could you share a few more details to help narrow down why this might be an issue, please?

    1. git config --list details of the repository in your example
    2. git version
    3. operating system and version

    Reproduction attempt

    Using a fork based on https://github.com/tinyfists/gh-nonsense, I'm attempting to reproduce this with a different fork/upstream as I want to avoid testing against cli/cli.

    os: MacOS 14.17.1
    git: 2.46.0

    In the last step, gh pr create does not error and continues on to prompt me for completing the PR creation.

    1. Clone fork outside of gh repo clone and setup remote

      $ git clone [email protected]:andyfeller/gh-nonsense.git
      Cloning into 'gh-nonsense'...
      remote: Enumerating objects: 46, done.
      remote: Counting objects: 100% (46/46), done.
      remote: Compressing objects: 100% (32/32), done.
      remote: Total 46 (delta 16), reused 33 (delta 5), pack-reused 0 (from 0)
      Receiving objects: 100% (46/46), 5.99 KiB | 5.99 MiB/s, done.
      Resolving deltas: 100% (16/16), done.
      
      $ cd gh-nonsense 
      $ git remote add upstream https://github.com/tinyfists/gh-nonsense
      
      $ git remote -v
      origin  [email protected]:andyfeller/gh-nonsense.git (fetch)
      origin  [email protected]:andyfeller/gh-nonsense.git (push)
      upstream        https://github.com/tinyfists/gh-nonsense (fetch)
      upstream        https://github.com/tinyfists/gh-nonsense (push)
      
      $ git config --list | cat
      branch.main.merge=refs/heads/main
      branch.main.remote=origin
      core.bare=false
      core.filemode=true
      core.ignorecase=true
      core.logallrefupdates=true
      core.precomposeunicode=true
      core.repositoryformatversion=0
      fetch.prune=true
      init.defaultbranch=main
      pull.rebase=true
      push.autosetupremote=true
      remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
      [email protected]:andyfeller/gh-nonsense.git
      remote.upstream.fetch=+refs/heads/*:refs/remotes/upstream/*
      remote.upstream.url=https://github.com/tinyfists/gh-nonsense
    2. Create testbranch from reproduction steps

      $ git switch -c testbranch
      Switched to a new branch 'testbranch'
      
      $ echo "hello world" > testfile.txt
      $ git add testfile.txt
      $ git commit -am "test commit"
      [testbranch 2ba1e6f] test commit
       1 file changed, 1 insertion(+)
       create mode 100644 testfile.txt
    3. Setup default remote and create PR

      $ gh repo set-default tinyfists/gh-nonsense
      ✓ Set tinyfists/gh-nonsense as the default repository for the current directory
      
      $ gh pr create
      ? Where should we push the 'testbranch' branch? andyfeller/gh-nonsense
      
      Creating pull request for andyfeller:testbranch into main in tinyfists/gh-nonsense
      
      ? Title 

    Relevant code

    existingPR, _, err := opts.Finder.Find(shared.FindOptions{
    Selector: ctx.HeadBranchLabel,
    BaseBranch: ctx.BaseBranch,
    States: []string{"OPEN"},
    Fields: []string{"url"},
    })
    var notFound *shared.NotFoundError
    if err != nil && !errors.As(err, &notFound) {
    return fmt.Errorf("error checking for existing pull request: %w", err)
    }

    func ParsePRRefs(currentBranchName string, branchConfig git.BranchConfig, parsedPushRevision string, pushDefault string, remotePushDefault string, baseRefRepo ghrepo.Interface, rems remotes.Remotes) (PullRequestRefs, error) {
    prRefs := PullRequestRefs{
    BaseRepo: baseRefRepo,
    }
    // If @{push} resolves, then we have all the information we need to determine the head repo
    // and branch name. It is of the form <remote>/<branch>.
    if parsedPushRevision != "" {
    for _, r := range rems {
    // Find the remote who's name matches the push <remote> prefix
    if strings.HasPrefix(parsedPushRevision, r.Name+"/") {
    prRefs.BranchName = strings.TrimPrefix(parsedPushRevision, r.Name+"/")
    prRefs.HeadRepo = r.Repo
    return prRefs, nil
    }
    }
    remoteNames := make([]string, len(rems))
    for i, r := range rems {
    remoteNames[i] = r.Name
    }
    return PullRequestRefs{}, fmt.Errorf("no remote for %q found in %q", parsedPushRevision, strings.Join(remoteNames, ", "))
    }

    parsePushRevision: func(branch string) (string, error) {
    return factory.GitClient.ParsePushRevision(context.Background(), branch)
    },

    cli/git/client.go

    Lines 476 to 483 in 42c0cb0

    // ParsePushRevision gets the value of the @{push} revision syntax
    // An error here doesn't necessarily mean something is broken, but may mean that the @{push}
    // revision syntax couldn't be resolved, such as in non-centralized workflows with
    // push.default = simple. Downstream consumers should consider how to handle this error.
    func (c *Client) ParsePushRevision(ctx context.Context, branch string) (string, error) {
    revParseOut, err := c.revParse(ctx, "--abbrev-ref", branch+"@{push}")
    return firstLine(revParseOut), err
    }

  4. pinned this issue on Jan 31, 2025
  5. neutrinoceros commented on Jan 31, 2025

    @neutrinoceros
    Author

    Thanks for working on this. Here are some more details

    git config list

    outputcredential.helper=osxkeychain user.name=<redacted> user.email=<redacted> init.defaultbranch=main merge.conflictstyle=zdiff3 diff.algorithm=histogram rerere.enabled=true branch.sort=-committerdate rebase.autostash=true rebase.autosquash=true alias.squash=!f() { : git show ; git -c sequence.editor=: rebase -i ${1:-@~10}; }; f alias.gone=! git fetch -p && git for-each-ref --format '%(refname:short) %(upstream:track)' | awk '$2 == "[gone]" {print $1}' | xargs -r git branch -D alias.switch-recent=!git branch --sort=-committerdate --format='%(refname:short)' | fzf --preview='git log --date=relative --color main..{}' | xargs git switch alias.primary=!f() { git branch -a | sed -n -E -e '/remotes.origin.ma(in|ster)$/s@remotes/origin/@@p'; }; f alias.ma=!f() { git checkout $(git primary) && git pull; }; f alias.maup=!f() { git ma && git pull upstream $(git primary) --ff-only && git push; }; f core.repositoryformatversion=0 core.filemode=true core.bare=false core.logallrefupdates=true core.ignorecase=true core.precomposeunicode=true [email protected]:neutrinoceros/gh-nonsense.git remote.origin.fetch=+refs/heads/*:refs/remotes/origin/* branch.main.remote=origin branch.main.merge=refs/heads/main remote.upstream.url=https://github.com/tinyfists/gh-nonsense remote.upstream.fetch=+refs/heads/*:refs/remotes/upstream/* remote.upstream.gh-resolved=base
    ❯ git version
    git version 2.48.1
    

    I'm on MacOS 15.2

  6. gaborbernat commented on Jan 31, 2025

    @gaborbernat

    I'm running into the same issue 🤔

  7. jtmcg commented on Feb 1, 2025

    @jtmcg
    Contributor

    Hey @neutrinoceros and @gaborbernat, I managed to mostly reproduce this locally on v2.66.0, but we shipped a hotfix today for #10352 that I suspect addresses this issue as well. I've tried to repro using the steps that gave me the same error you have reported here and things were behaving as expected.

    Could y'all give this another go once you upgrade to v2.66.1 and let us know if this is fixed for you? Thanks!

  8. jaymzh commented on Feb 1, 2025

    @jaymzh

    I can confirm 2.66.1 fixes this for me.

  9. neutrinoceros commented on Feb 1, 2025

    @neutrinoceros
    Author

    Me too ! Thanks for promptly addressing this issue !

  10. ssbarnea commented on Feb 1, 2025

    @ssbarnea

    @neutrinoceros time to close it.

  11. katty115 commented on Feb 17, 2025

    @katty115
  12. unpinned this issue on Feb 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't workingcoreThis issue is not accepting PRs from outside contributorsgh-prrelating to the gh pr commandmore-info-neededMore info needed from user/contributorneeds-triageneeds to be reviewedpriority-2Affects more than a few users but doesn't prevent core functions

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions