You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Enhance gh pr create to support cross repo pull requests within the same organization #10093
Describe the feature or problem you’d like to solve
gh pr create -H user:branch is limited to creating cross repo pull requests between an upstream repository and a user-owned fork due to createPullRequest mutation limitation in the headRefName field. Instead, these types of cross repo pull requests should specify the GraphQL ID of the upstream repository using headRepositoryId field.
Ideally, the -H, --head branch flag could be used with user or organization logins.
@andyfeller from an implementation point of view, are you thinking that we could look at the <owner> portion of <owner>:<branch> and lookup the headRepositoryId if it appears to be the same owner as the repo owning the base branch?
Reacted by Andy Feller and Chindriș Mihai - Alexandru
@andyfeller from an implementation point of view, are you thinking that we could look at the <owner> portion of <owner>:<branch> and lookup the headRepositoryId if it appears to be the same owner as the repo owning the base branch?
Good question. 🤔 Let me dump my thoughts to think through this a bit...
Stream of thought
When we create a cross repo pull requests within our acceptance test, it shows up as:
Neither the base or head demonstrate the repositories involved; simple who owns them and the branches.
In the scenario where we're creating pull requests, it's a question of whether the pull request spans:
2 branches in the same repo
2 branches across the parent and fork repos
If there is no way to create a pull request from completely unrelated repositories AND cross repo pull requests must traverse the parent/child relationship, then perhaps it isn't important to denote the repository in -H?
I was primarily thinking about creating a pull requests with changes from the fork/child repo to the upstream/parent repo, however I wonder if there are use cases for the reverse of creating a pull request from the parent to the child. 🤔
Additionally, Repository contains a forks field to identify and traverse children.
We could use the optional <owner> as an indicator that this is a cross repo pull request, resolve the parent, maybe throw an error if the information we get doesn't match while creating the PR if they do?
I'm sorry Andy, I've read your message a few times and I'm not really sure how to reply to the stream of thought. It's not that I don't like it, I'm just not following 😅 .
If there is no way to create a pull request from completely unrelated repositories AND cross repo pull requests must traverse the parent/child relationship, then perhaps it isn't important to denote the repository in -H?
I don't see how one follows from the other.
We could use the optional as an indicator that this is a cross repo pull request, resolve the parent, maybe throw an error if the information we get doesn't match while creating the PR if they do?
It seems reasonable to me that if you provide <owner> you are indicating a cross repo PR. So my question was whether we would be able to use that to go find the head repository ID? In practice I'm not sure it's possible because an org may contain many forks, and each of them may have a branch of the right name. Maybe this is what you were implying with:
Neither the base or head demonstrate the repositories involved; simple who owns them and the branches.
I'm just not sure whether you had a specific implementation in mind for this. If so, can you outline what it would be.
Reacted by Andy Feller
Reacted by Andy Feller and Chindriș Mihai - Alexandru
If there is no way to create a pull request from completely unrelated repositories AND cross repo pull requests must traverse the parent/child relationship, then perhaps it isn't important to denote the repository in -H?
I don't see how one follows from the other.
😞 Sorry for getting lost in the train of thought, that said I think you understand what I was rambling on about. Thank you for patience and working with what was provided. 🙇
It seems reasonable to me that if you provide <owner> you are indicating a cross repo PR. So my question was whether we would be able to use that to go find the head repository ID? In practice I'm not sure it's possible because an org may contain many forks, and each of them may have a branch of the right name. Maybe this is what you were implying with:
Neither the base or head demonstrate the repositories involved; simple who owns them and the branches.
I'm definitely trying to figure out whether the user invoking gh pr create needs to explicitly tell use about the upstream repo as part of -H ... or not.
Again, gh pr create -H username:branch creates a cross-repo pull request from a user fork of its upstream repo.
-H username:branch is leaking a technical detail of the headRefName field in the CreatePullRequestInput used under the covers.
-H username:branch does not require the name of the repository because the GitHub API is figuring that out on the backend.
In order to create cross-repo pull requests between organization repositories, gh pr create needs to provide that information in the form of headRepositoryId to CreatePullRequestInput
Does the user provide this? If so, is this a different form of -H, --head flag like -H org/repo:branch?
Does the GitHub CLI attempt to figure out the base repository based on forks info within the GitHub API, removing the need for modifying -H input format?
At the time I reported this, I was worried about including another obscure, undocumented format for the -H, --head flag when trying to think about sourcing headRepositoryId information.
Practical example
Here are 2 private repositories I created within my test organization, one as a fork of the other:
Since we use the local repository context or -R, --repo flag to identify the repository, I was thinking maybe that is used and we pull the parent information since there can only be 1 parent. That way, gh pr create -H ... doesn't require another format and there is less for the user to provide.
I think I understand your idea more completely, thanks for taking the time.
Since we use the local repository context or -R, --repo flag to identify the repository, I was thinking maybe that is used and we pull the parent information since there can only be 1 parent. That way, gh pr create -H ... doesn't require another format and there is less for the user to provide.
I'm not sure how we address the following scenario, which I didn't explain very well earlier.
org/
repo
repo-fork-1
repo-fork-2
Both repo-fork-1 and repo-fork-2 have feature-branch.
I run gh pr --repo org/repo create -H org:feature-branch.
How do we find the right head branch to use?
Sorry if I'm misunderstanding you. I think this is just a bit of a gnarly topic with a lot of moving parts.
My work recently started requiring that we move our forks outside of personal namespaces and put them into an organization. Unfortunately, the place where we can create forks is separate from where our repositories live, so this comes up and creates some weird failures.
Id like to help resolve this so that we can maintain use of CLI.
It seems to me that you could figure out the repository to use by looking at the remote info, or doing a lookup when selecting where to push.
In my case, gh pr correctly identified where to push but then fails to create the repository because it doesnt full in the graph ql data correctly. I'll have to look more closely at this tomorrow, but it seems like we should be able to solve this without needing to have the user provide too much additional data.
Since we use the local repository context or -R, --repo flag to identify the repository, I was thinking maybe that is used and we pull the parent information since there can only be 1 parent. That way, gh pr create -H ... doesn't require another format and there is less for the user to provide.
I'm not sure how we address the following scenario, which I didn't explain very well earlier.
org/
repo
repo-fork-1
repo-fork-2
Both repo-fork-1 and repo-fork-2 have feature-branch.
I run gh pr --repo org/repo create -H org:feature-branch.
How do we find the right head branch to use?
Sorry if I'm misunderstanding you. I think this is just a bit of a gnarly topic with a lot of moving parts.
Mrmmm good question and 💯 on the gnarly aspect of it! Thanks for the example as I definitely hadn't considered this. 🤔
Would --repo org/repo just change how we resolve headRepositoryId below?
Previously, I was assuming someone was calling gh pr create -H org:feature-branch from a local repository cloned. In the event someone provides --repo owner/name, then gh pr create should be focused on creating the PR from the remote repo instead, but repositoryId variable below would be the same parent.
-R to specify the target repo to create the PR in. Without the -R, this is determined automatically?
-H to specify the branch that we want the fork to use. This defaults to the current branch, but you can also specify with "owner:branch" to try and pick up a remote branch. However, this specifically does not include the repository name as it essentially assumes the owner has a single unique fork, but with organizations that won't be the case?
With a plain "gh pr create", the flow is something like this:
ask/determine where the PR is created
assume the current branch is what we want as the head
ask/determine where we will push the branch
push the branch to the remote
create the PR over the API
I think for plain gh pr create, at step 3, we should remember where we pushed and do a lookup to get the headRepositoryID, since we already know we're pushing to that remote.
That would solve my issue, but does not handle the cases with the options for -H to specify the head without pushing.
Is there any other identifying information we can use to select the proper fork when dealing with multiple forks under a given organization? If not, I think extending -H to include repository name somehow would be required.
When making PRs from a local repository, we could use remote info to limit the list to the remotes which the user has added. If we find multiple forks, we could then put up a dialog to ask the user which one they wanted?
For non-interactive modes we would need a flag or extension of -H, I think.
Looking at the create code in https://github.com/cli/cli/blob/trunk/pkg/cmd/pr/create/create.go#L930 we already have headRepo in the create context. I'm thinking at least for the case without -H, we can extend the PR creation to do a proper lookup of the headRepositoryId via the headRepo.
I made an initial attempt at including the headRepositoryId when we know it, at #10253
I submitted as a draft since I have limited go experience and am not sure how to even execute tests. I think this approach will be helpful for the most common use case where we are automatically determining the head repository, as it doesn't require user intervention. However, it doesn't solve the general case with --head, as I am unsure what the best solution is there. It is also likely that this PR doesn't quite work as-is, since I am unsure how to go about testing it.
Activity
williammartin commentedon Dec 17, 2024
@andyfeller from an implementation point of view, are you thinking that we could look at the
<owner>portion of<owner>:<branch>and lookup theheadRepositoryIdif it appears to be the same owner as the repo owning the base branch?andyfeller commentedon Dec 18, 2024
Good question. 🤔 Let me dump my thoughts to think through this a bit...
Stream of thought
When we create a cross repo pull requests within our acceptance test, it shows up as:
Neither the base or head demonstrate the repositories involved; simple who owns them and the branches.
In the scenario where we're creating pull requests, it's a question of whether the pull request spans:
If there is no way to create a pull request from completely unrelated repositories AND cross repo pull requests must traverse the parent/child relationship, then perhaps it isn't important to denote the repository in
-H?I was primarily thinking about creating a pull requests with changes from the fork/child repo to the upstream/parent repo, however I wonder if there are use cases for the reverse of creating a pull request from the parent to the child. 🤔
As far as resolving
headRepositoryId, GraphQL exposesparentfield withinRepositoryobject where we can get the node ID that should be used.results in:
{ "data": { "repository": { "name": "fork", "id": "R_kgDONfdxzw", "isFork": true, "isInOrganization": true, "parent": { "name": "upstream", "id": "R_kgDONfdwnQ", "isFork": false, "isInOrganization": true } } } }Additionally,
Repositorycontains aforksfield to identify and traverse children.We could use the optional
<owner>as an indicator that this is a cross repo pull request, resolve theparent, maybe throw an error if the information we get doesn't match while creating the PR if they do?williammartin commentedon Dec 19, 2024
I'm sorry Andy, I've read your message a few times and I'm not really sure how to reply to the stream of thought. It's not that I don't like it, I'm just not following 😅 .
I don't see how one follows from the other.
It seems reasonable to me that if you provide
<owner>you are indicating a cross repo PR. So my question was whether we would be able to use that to go find the head repository ID? In practice I'm not sure it's possible because an org may contain many forks, and each of them may have a branch of the right name. Maybe this is what you were implying with:I'm just not sure whether you had a specific implementation in mind for this. If so, can you outline what it would be.
andyfeller commentedon Jan 9, 2025
😞 Sorry for getting lost in the train of thought, that said I think you understand what I was rambling on about. Thank you for patience and working with what was provided. 🙇
I'm definitely trying to figure out whether the user invoking
gh pr createneeds to explicitly tell use about the upstream repo as part of-H ...or not.Again,
gh pr create -H username:branchcreates a cross-repo pull request from a user fork of its upstream repo.-H username:branchis leaking a technical detail of theheadRefNamefield in the CreatePullRequestInput used under the covers.-H username:branchdoes not require the name of the repository because the GitHub API is figuring that out on the backend.In order to create cross-repo pull requests between organization repositories,
gh pr createneeds to provide that information in the form ofheadRepositoryIdto CreatePullRequestInputDoes the user provide this? If so, is this a different form of
-H, --headflag like-H org/repo:branch?Does the GitHub CLI attempt to figure out the base repository based on
forksinfo within the GitHub API, removing the need for modifying-Hinput format?At the time I reported this, I was worried about including another obscure, undocumented format for the
-H, --headflag when trying to think about sourcingheadRepositoryIdinformation.Practical example
Here are 2 private repositories I created within my test organization, one as a fork of the other:
Since we use the local repository context or
-R, --repoflag to identify the repository, I was thinking maybe that is used and we pull the parent information since there can only be 1 parent. That way,gh pr create -H ...doesn't require another format and there is less for the user to provide.Does that make more sense, @williammartin?
williammartin commentedon Jan 10, 2025
I think I understand your idea more completely, thanks for taking the time.
I'm not sure how we address the following scenario, which I didn't explain very well earlier.
Both
repo-fork-1andrepo-fork-2havefeature-branch.I run
gh pr --repo org/repo create -H org:feature-branch.How do we find the right head branch to use?
Sorry if I'm misunderstanding you. I think this is just a bit of a gnarly topic with a lot of moving parts.
jacob-keller commentedon Jan 15, 2025
My work recently started requiring that we move our forks outside of personal namespaces and put them into an organization. Unfortunately, the place where we can create forks is separate from where our repositories live, so this comes up and creates some weird failures.
Id like to help resolve this so that we can maintain use of CLI.
It seems to me that you could figure out the repository to use by looking at the remote info, or doing a lookup when selecting where to push.
In my case, gh pr correctly identified where to push but then fails to create the repository because it doesnt full in the graph ql data correctly. I'll have to look more closely at this tomorrow, but it seems like we should be able to solve this without needing to have the user provide too much additional data.
andyfeller commentedon Jan 15, 2025
Mrmmm good question and 💯 on the gnarly aspect of it! Thanks for the example as I definitely hadn't considered this. 🤔
Would
--repo org/repojust change how we resolveheadRepositoryIdbelow?Previously, I was assuming someone was calling
gh pr create -H org:feature-branchfrom a local repository cloned. In the event someone provides--repo owner/name, thengh pr createshould be focused on creating the PR from the remote repo instead, butrepositoryIdvariable below would be the sameparent.jacob-keller commentedon Jan 15, 2025
Ultimately we need to know a few things:
We have two flags currently:
-R to specify the target repo to create the PR in. Without the -R, this is determined automatically?
-H to specify the branch that we want the fork to use. This defaults to the current branch, but you can also specify with "owner:branch" to try and pick up a remote branch. However, this specifically does not include the repository name as it essentially assumes the owner has a single unique fork, but with organizations that won't be the case?
With a plain "gh pr create", the flow is something like this:
I think for plain gh pr create, at step 3, we should remember where we pushed and do a lookup to get the headRepositoryID, since we already know we're pushing to that remote.
That would solve my issue, but does not handle the cases with the options for -H to specify the head without pushing.
Is there any other identifying information we can use to select the proper fork when dealing with multiple forks under a given organization? If not, I think extending -H to include repository name somehow would be required.
When making PRs from a local repository, we could use remote info to limit the list to the remotes which the user has added. If we find multiple forks, we could then put up a dialog to ask the user which one they wanted?
For non-interactive modes we would need a flag or extension of -H, I think.
jacob-keller commentedon Jan 15, 2025
Looking at the create code in https://github.com/cli/cli/blob/trunk/pkg/cmd/pr/create/create.go#L930 we already have headRepo in the create context. I'm thinking at least for the case without -H, we can extend the PR creation to do a proper lookup of the headRepositoryId via the headRepo.
I'm unsure how to handle the case with --head/-H.
jacob-keller commentedon Jan 16, 2025
I made an initial attempt at including the headRepositoryId when we know it, at #10253
I submitted as a draft since I have limited go experience and am not sure how to even execute tests. I think this approach will be helpful for the most common use case where we are automatically determining the head repository, as it doesn't require user intervention. However, it doesn't solve the general case with --head, as I am unsure what the best solution is there. It is also likely that this PR doesn't quite work as-is, since I am unsure how to go about testing it.
13 remaining items
HACKER007-SHIP-IT commentedon Dec 31, 2025
HACKER007-SHIP-IT commentedon Jan 2, 2026
lyonstim247-lgtm commentedon Mar 23, 2026
abdoo66378-art commentedon Apr 30, 2026
Address CodeRabbit review of PR #4
Make analyze-cve portable to non-Ambient runtimes (Prow CI) (#4)
Lok-thiek commentedon Sep 20, 2026
Lok-thiek commentedon Sep 20, 2026