Skip to content

'gh pr create' fails if skipping pushing with "GraphQL error: Head sha can't be blank, Base sha can't be blank, No commits between master and <branch>, Head ref must be a branch" #2691

Open

Description

@phil-blain

Describe the bug

Under some circumstances (not sure exactly why, see below), if I choose to skip pushing the current branch, PR creation fails with the following error:

GraphQL error: Head sha can't be blank, Base sha can't be blank, No commits between master and , Head ref must be a branch"

This is on 1.4.0 but also happened on 1.3.1.

Steps to reproduce the behavior

I think this should reproduce the problem. I'm pretty sure the bug is linked to the upstream configuration for the current branch :

  1. Create a topic branch, and set the Git upstream configuration to the upstream branch where this topic will eventually be integrated (see Detect push target for local branches without upstream configuration #575): git checkout -b my-topic upstream/master
  2. Add some commits, and push to your fork : git push origin HEAD
  3. Create the PR with gh: gh pr create
  4. Choose "Skip pushing the branch" when asked where to push. I already pushed it myself, and I don't want gh to mess with my upstream configuration (i.e. I want to avoid gh doing git branch --set-upstream-to=origin/$(git branch --show-current) or git push -u origin $(git branch --show-current)), a behaviour which can't be disabled at the moment).
  5. Enter title
  6. Edit body
  7. Submit
  8. Experience error: pull request create failed: GraphQL error: Head sha can't be blank, Base sha can't be blank, No commits between master and my-topic, Head ref must be a branch

Expected vs actual behavior

I expected the PR creation to succeed. The GraphQL error seems to imply that gh is making a incorrect API request because (I assume) it can't correctly compute the required arguments.

Logs

## Git state before attempting PR creation
# upstream branch is upstream/master
$ git rev-parse --symbolic-full-name  @{upstream}
refs/remotes/upstream/master
# current branch is one commit ahead of its upstream
$ git log --oneline --decorate @{upstream}..HEAD
494173a586 (HEAD -> fix-linkgit-git1, origin/fix-linkgit-git1) git.txt: fix typos in 'linkgit' macro invocation
# current branch is already pushed to my fork
$ git  log --oneline --decorate origin/$(git branch --show-current)..HEAD
# empty

# configured remote for 'gh' is 'ggg', which I do not have push access to:
$ git config --get-regexp  'remote.*.gh-resolved'
remote.ggg.gh-resolved base

# Try creating the PR:
$ gh pr create 
? Where should we push the 'fix-linkgit-git1' branch? Skip pushing the branch

Creating pull request for fix-linkgit-git1 into master in gitgitgadget/git

? Title Fix typo in 'linkgit' macro invocation
? Body <Received>
? What's next? Submit

X operation failed. To restore: gh pr create --recover /var/folders/lr/r6n2057j0dzd4gdb614fp0740000gp/T/gh303112606.json

pull request create failed: GraphQL error: Head sha can't be blank, Base sha can't be blank, No commits between master and fix-linkgit-git1, Head ref must be a branch

Another thing I noticed while debugging this: If I choose to open the PR against my own fork (-R phil-blain/git), it works., even if I do not skip pushing the branch.

Activity

  1. phil-blain commented on Jan 14, 2021

    @phil-blain
    Author

    Here are some standalone reproduction steps:

    1. I forked cli/cli
    2. I cloned my fork
    3. I added cli/cli as a remote named "upstream",
    4. I created a branch test with "upstream/trunk" as upstream, and committed some changes: git checkout -b test upstream/trunk && date>>README.md && git commit -am test
    5. I pushed to my fork: git push origin HEAD
    6. I tried creating a PR with DEBUG=api gh pr create -b "Trying to reproduce https://github.com/cli/cli/issues/2691" -t "Test PR to reproduce https://github.com/cli/cli/issues/2691" --head $(git branch --show-current)

    Here is the request that is sent:

    {
        "query": "\n\t\tmutation PullRequestCreate($input: CreatePullRequestInput!) {\n\t\t\tcreatePullRequest(input: $input) {\n\t\t\t\tpullRequest {\n\t\t\t\t\tid\n\t\t\t\t\turl\n\t\t\t\t}\n\t\t\t}\n\t}",
        "variables": {
            "input": {
                "baseRefName": "trunk",
                "body": "Trying to reproduce https://github.com/cli/cli/issues/2691",
                "draft": false,
                "headRefName": "test",
                "repositoryId": "MDEwOlJlcG9zaXRvcnkyMTI2MTMwNDk=",
                "title": "Test PR to reproduce https://github.com/cli/cli/issues/2691"
            }
        }
    }
    • If I remove --head $(git branch --show-current), and choose to skip pushing when asked, I get the same result.
    • If I add -R phil-blain/cli, I get the same kind of request, and it succeeds:
    {
        "query": "\n\t\tmutation PullRequestCreate($input: CreatePullRequestInput!) {\n\t\t\tcreatePullRequest(input: $input) {\n\t\t\t\tpullRequest {\n\t\t\t\t\tid\n\t\t\t\t\turl\n\t\t\t\t}\n\t\t\t}\n\t}",
        "variables": {
            "input": {
                "baseRefName": "trunk",
                "body": "Trying to reproduce https://github.com/cli/cli/issues/2691",
                "draft": false,
                "headRefName": "test",
                "repositoryId": "MDEwOlJlcG9zaXRvcnkzMjk0ODI5Nzk=",
                "title": "Test PR to reproduce https://github.com/cli/cli/issues/2691"
            }
        }
    }
    • If I remove --head $(git branch --show-current), and choose to push to my fork (phil-blain/cli) when prompted, this is the request that is sent, and it succeeds:
    {
        "query": "\n\t\tmutation PullRequestCreate($input: CreatePullRequestInput!) {\n\t\t\tcreatePullRequest(input: $input) {\n\t\t\t\tpullRequest {\n\t\t\t\t\tid\n\t\t\t\t\turl\n\t\t\t\t}\n\t\t\t}\n\t}",
        "variables": {
            "input": {
                "baseRefName": "trunk",
                "body": "Trying to reproduce https://github.com/cli/cli/issues/2691",
                "draft": false,
                "headRefName": "phil-blain:test",
                "repositoryId": "MDEwOlJlcG9zaXRvcnkyMTI2MTMwNDk=",
                "title": "Test PR to reproduce https://github.com/cli/cli/issues/2691"
            }
        }
    }

    So, headRefName is set to phil-blain:test, whereas it is only test in the failing requests. I'm guessing that's where the bug comes from.

  2. phil-blain commented on Jan 14, 2021

    @phil-blain
    Author

    Interestingly, I tried with --head phil-blain:$(git branch --show-current) instead, and this succeeded:

    {
        "query": "\n\t\tmutation PullRequestCreate($input: CreatePullRequestInput!) {\n\t\t\tcreatePullRequest(input: $input) {\n\t\t\t\tpullRequest {\n\t\t\t\t\tid\n\t\t\t\t\turl\n\t\t\t\t}\n\t\t\t}\n\t}",
        "variables": {
            "input": {
                "baseRefName": "trunk",
                "body": "Trying to reproduce https://github.com/cli/cli/issues/2691",
                "draft": false,
                "headRefName": "phil-blain:test",
                "repositoryId": "MDEwOlJlcG9zaXRvcnkyMTI2MTMwNDk=",
                "title": "Test PR to reproduce https://github.com/cli/cli/issues/2691"
            }
        }
    }
    
  3. mislav commented on Jan 14, 2021

    @mislav
    Contributor

    Thanks for the detailed reproduction steps! I think the problem is that we don't detect properly that your branch is already published to origin unless it has git upstream configuration set up #575

    We do detect it if it's fully pushed, but as you've mentioned, your local branch was one commit ahead.

  4. phil-blain commented on Jan 14, 2021

    @phil-blain
    Author

    Thanks for the detailed reproduction steps! I think the problem is that we don't detect properly that your branch is already published to origin unless it has git upstream configuration set up #575

    Yes, I agree.

    We do detect it if it's fully pushed, but as you've mentioned, your local branch was one commit ahead.

    It was one commit ahead of @{upstream} (upstream/trunk), but it was fully pushed to @{push} ( origin/test).

  5. mislav commented on Jan 14, 2021

    @mislav
    Contributor

    It was one commit ahead of @{upstream} (upstream/trunk), but it was fully pushed to @{push} ( origin/test).

    We don't have support for @{push}, so only @{upstream} was taken into account, and since there was a mismatch, gh could not determine where the branch was pushed.

    resolvedRefs, _ := git.ShowRefs(refsForLookup...)
    if len(resolvedRefs) > 1 {
    for _, r := range resolvedRefs[1:] {
    if r.Hash != resolvedRefs[0].Hash {
    continue
    }
    for _, tr := range trackingRefs {
    if tr.String() != r.Name {
    continue
    }
    return &tr

    Sometimes I think that our branch push detection is trying to be too smart. Maybe we can just assume that a branch was pushed to a remote if there is a same-named branch on the remote. That could be prone to false positives, but I think they would be rarer than current false negatives.

  6. phil-blain commented on Jan 15, 2021

    @phil-blain
    Author

    Why not just check the local hashes? in the case above, "test" and "origin/test" point to the same hash, so it means the branch was pushed... Then you can't have "false positives" , no ?

    Also, I think the doc could be clearer about the "owner:branch" syntax for the  --head argument. I only tried it after reading the code, and only afterwards realized that gh pr create --help had "gh pr create --base develop --head monalisa:feature" as the last example...

    For me a branch is a Git term, and "phil-blain:test" is not a branch, so I think the documentation could be clearer in that regards.

  7. added
    priority-2Affects more than a few users but doesn't prevent core functions
    on Jan 28, 2021
  8. deleugpn commented on Aug 5, 2021

    @deleugpn

    Who is the owner of a branch?

  9. tmandry commented on Sep 4, 2021

    @tmandry

    I just hit this and it caused the whole PR description I'd written to disappear. Better error recovery would be nice.

    Edit for anyone who hits this: I was able to find a copy in vim's backup dir.

  10. mislav commented on Sep 6, 2021

    @mislav
    Contributor

    @tmandry I'm sorry that you almost lost your work. Are you running a recent version of gh? We've had the --recover option for failed gh pr create since v1.3, and if that never showed up for you, we'd appreciate an open issue about it!

  11. tmandry commented on Sep 8, 2021

    @tmandry

    Ah, mine's v1.2. I'll upgrade then! Thanks for the helpful response.

  12. MikePendo commented on Oct 31, 2021

    @MikePendo

    same issue here

  13. imsanjoykb commented on Nov 27, 2021

    @imsanjoykb

    I use ---
    gh pr create --title "The bug is fixed" --body "Everything works again"

    but getting error

  14. julianwagle commented on Apr 19, 2022

    @julianwagle

    I kept getting this error - I was calling the wrong branch name in --head. Hopefully that can help someone down the line.

  15. 8 remaining items

  16. cchiriac518 commented on Aug 4, 2023

    @cchiriac518

    Hey. I had the same issue and in my case the issue is that I put my branches in the wrong order (head and base were reversed)

  17. added
    gh-prrelating to the gh pr command
    on Oct 2, 2023
  18. added a commit that references this issue on Jul 28, 2024
  19. amzar96 commented on Mar 4, 2025

    @amzar96

    Hello, I faced the same issue. It only occurs when creating a pull request using CLI.

  20. fredleger commented on Apr 4, 2025

    @fredleger

    same started after i guess git update ?
    MacOS Silicon M1 / git version 2.49.0

  21. added a commit that references this issue on May 28, 2025
  22. itinance commented on Aug 28, 2025

    @itinance

    running into exact this issue today gh version 2.78.0 (2025-08-21)

  23. LucaPrete commented on Sep 9, 2025

    @LucaPrete

    +1 same issue

  24. tedwardd commented on Oct 22, 2025

    @tedwardd

    FWIW, here is my workaround for gh create -f not working with git worktrees:

    gh pr create -B master -H $(git branch --show-current) -t "[$(git branch --show-current | cut -d'/' -f2)] $(git show -s --format=%s|cut -d']' -f2 |xargs)"'
    - Creating alias for cpr: !gh pr create -B master -H $(git branch --show-current) -t "[$(git branch --show-current | cut -d/ -f2)] $(git show -s --format=%s)" -b "$(git` show -s --format=%s)"
    

    I create branches with the naming convention ${username}/${jira_ticket} and always want my PR to be formatted with [${jira_ticket}] in front. The command above sets the title and body to the last commit message and prepends the jira ticket to the title. You can omit the $(git branch --show-current) from the title if you do not want that part.

  25. fredleger commented on Oct 27, 2025

    @fredleger

    I create branches with the naming convention ${username}/${jira_ticket}

    Interesting, i also created the branch PR with à / in it (something like feat/some-cool-feature). Is it the case of the others as well ?

  26. added theissue type on Mar 10, 2026
  27. toddjonker commented on Sep 9, 2026

    @toddjonker

    This error also comes up using gh stack link, in my case while using Jujutsu. AFAICT I'm doing exactly what the documentation directs, but it still fails with this inscrutable message.

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 isn't workinggh-prrelating to the gh pr commandpitchpitched internally for prioritisationpriority-2Affects more than a few users but doesn't prevent core functions

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions