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
Describe the feature or problem you’d like to solve
When working against a feature branch with branch protection (or rulesets) set, it would be very helpful to be able to set the default branch for subsequent gh pr create commands.
Proposed solution
I can think of a couple options numbered according to my preference, as well as for ease of reference in comments.
Figure out the closest branch (at least local, if not remote) and use that as the base. To avoid breaking current behavior, a new switch could be added e.g., --auto-base. That is, what is a branch that contains a more recent commit that is not only in the current branch.
Set a marker in .git/config (with worktree support, of course) much like gh repo set-default does. The downside is that you have to remember to unset or move this.
Additional context
Major feature work may happen in a feature branch while the repo stays on main or something, so most contributors' PRs should be against main and only those virtual team members working on the feature branch should use it as a base for PRs.
gh is in a unique position to do something here because creating a pull request (outside of email/mailbox) is outside the scope of Git, and there's probably no great way for the web site to do this (well, maybe isolated storage to roam or even a local cookie).
@williammartin@andyfeller what do you think of this proposal? Any other ideas? I'm working primarily against a feature branch currently and this keeps biting me again and again. Ideally, it's automatic but I appreciate that would be a breaking behavior change. Maybe something to consider for v3, though.
What would be nice is if GitHub implemented an endpoint / query to do this based on remote info since PRs are opened against your knowledge of remote branches (well, local to GitHub). Using the local branches is problematic because some people - like me - tend to prune which branches in a large mono repo are fetched. So the local client may not have the most reliable info.
I've played around with existing queries and found some ways to do this remotely, but it requires a lot of chatter with the GraphQL endpoint so it may not be the best solution for this (slow).
Hey @heaths, before talking about solutions I just want to make sure I understand the situation:
There is a long-lived feature branch
PRs should be going to that feature branch instead of main
Remembering to add --base each time is annoying?
How do branch protections or rulesets come into the picture here?
So then your suggestion is that we could have an --auto-base flag that looks at the git history (ideally remotely) to determine the most likely branch that this PR should be opened against?
That's correct. I think we had talked about it in our meeting a while back, but it's been a while. It's not so much that passing --base is annoying, but that it's easy to forget and a few more annoying things fall out of that as a result:
The PR title is likely just the branch name because you likely have > 1 commit.
Similarly, the PR description is a list of the commit titles and any descriptions commits might've had. In both cases you have to manually copy the commit title and optional description back to the PR.
If the GitHub Actions in that branch and any branch policies are different, they don't retrigger automatically if you re-target the baseline and fix up the title/description. I've found you have to rebase locally and force push.
So cleaning up after forgetting is the annoyance...if people even notice.
@heaths : if I understand your explanation, you're working on feature-a in the following diagram wanting to target develop for PRs created rather than main.
In this scenario, I can understand wanting to avoid wasted GitHub Actions runs and time spent because the wrong branches are targeted. Much less the other frustrations mentioned above, so I'm 👍 around the idea in general.
Figure out the closest branch (at least local, if not remote) and use that as the base. To avoid breaking current behavior, a new switch could be added e.g., --auto-base. That is, what is a branch that contains a more recent commit that is not only in the current branch.
I would imagine having 1) a new command flag and 2) a new configuration option would allow people to try and enable the feature.
How many scenarios are we accounting for?
I can see several permutations:
whether the branch is created locally or remotely
whether the branch is created from default branch, feature branch, tag
whether the repository is a fork or not
How do branch protections or rulesets come into the picture here?
I'd like to hear about any specifics on branch protections or rulesets involved as I normally assume this just blocks people from pushing commits to specific branches directly, requiring developers to jump through different but familiar hoops for opening PRs.
I think whether the branch is local or not and from what commit it was branched is moot compared to what the PR should target. Because the action is to create a PR against the remote (i.e., GitHub), what it should target has to be remote. Now, that said, if the concern is that perhaps the dev forked from a branch that hasn't been pushed yet, but I'd imagine that's a pretty rare case and many of those times, it's probably more of a "placeholder" - a "temporary tag" to easily go back from and try a different angle. If that assumption holds true in many of those cases, then it still comes down to what remote branch on GitHub should be the target e.g., develop in your diagram.
In our case - and this may be uncommon, but plausible in other cases - our configured workflows and branches are different for main and develop (in your diagram; we call it feature/track2 but that's not important here). Significantly different, in fact, which is why it doesn't just waste agent time. If we switch the target branch later after jobs have already run, the workflows aren't rerun and we have to push a new commit (perhaps empty or just rebase HEAD) to get the right jobs to trigger.
I do like the idea of some sort of configuration that could, perhaps, be stored on the branch much like your gh-resolved = base on remotes, or (I just found out) vscode-merge-base on branches (for the GitHub Issues and Pull Requests VSCode extension, no doubt). In fact, maybe the CLI could even fall back to that since we're all one big happy family.
I once again forgot to set the --base and even after I switched to the right target via gh pr edit, I still had to git commit --amend && git push --force to get the right checks to trigger.
I think whether the branch is local or not and from what commit it was branched is moot compared to what the PR should target. Because the action is to create a PR against the remote (i.e., GitHub), what it should target has to be remote. Now, that said, if the concern is that perhaps the dev forked from a branch that hasn't been pushed yet, but I'd imagine that's a pretty rare case and many of those times, it's probably more of a "placeholder" - a "temporary tag" to easily go back from and try a different angle. If that assumption holds true in many of those cases, then it still comes down to what remote branch on GitHub should be the target e.g., develop in your diagram.
We're both in agreement — PRs ultimately care about a remote branch to target — which I predict is typically the source of the branch whether created locally or remotely.
The questions were an attempt to capture more concrete, practical acceptance criteria on how gh will behave in various situations.
In our case - and this may be uncommon, but plausible in other cases - our configured workflows and branches are different for main and develop (in your diagram; we call it feature/track2 but that's not important here). Significantly different, in fact, which is why it doesn't just waste agent time. If we switch the target branch later after jobs have already run, the workflows aren't rerun and we have to push a new commit (perhaps empty or just rebase HEAD) to get the right jobs to trigger.
Thank you for sharing the additional context! 👐
This scenario makes sense and is only an extension of how branch protection rules / repository rulesets are used.
I do like the idea of some sort of configuration that could, perhaps, be stored on the branch much like your gh-resolved = base on remotes, or (I just found out) vscode-merge-base on branches (for the GitHub Issues and Pull Requests VSCode extension, no doubt). In fact, maybe the CLI could even fall back to that since we're all one big happy family.
Your suggestion of extending gh awareness of VS Code configuration is not a bad idea.
My general concern is understanding how VS Code sets this and how this relates to gh working. Depending on how stable and predictable it is, it could be an option.
Do you have any more information you can share? Links?
I see this in code here but I was hoping for more information on how VS Code users trigger this behavior in the IDE.
I can start a thread with the owners, or get them to reply here - whichever they prefer. I think it would be best if gh sets its own, but could see falling back to vscode's for this purpose only. Or maybe not. But at least having its own marker, gh could be configured separately for whatever reason devs may have.
VS Code's built in git extension doesn't know that GitHub exists as the git remotes could be non-GitHub, so we'll always want to compute the merge base there.
Long term, I still think the algorithm for determining the target branch should actually be implemented in GitHub's GraphQL and/or REST APIs.
This seems reasonable! If this existed then I would say GHPR should always try to use this and fall back to what the built-in git extension provides if for some reason GH doesn't know about a merge base.
Since vscode-merge-base is meant to be generic I can see not unifying but it might still be good for us to consider falling back to it if your algorithm is comparable. Could you summarize, or is its pretty straightforward in open source code?
Given that github-pr-merge-base is deprecated (IMO, I agree it might be good to remove to avoid confusion) and vscode-merge-base defines the algorithm @williammartin is fine with using, I do think it makes sense to define our on gh-merge-base but fall back to checking for vscode-merge-base if gh-merge-base is undefined, or go through the algorithm to set gh-merge-base, agreed?
@williammartin I'd also like to put this in cli/go-gh if that's okay - and if it still supports stubbing out mocks for testing in cli/cli. Could be useful to extensions, and there are already some git APIs mirrored there (and, oddly, duplicated in cli/cli).
@andyfeller@williammartin what are next steps on this? Has anyone talked to the team that owns the GraphQL (or at least orchestrates the various features added to it) about the idea? Since the commit graph would have to be known, the best idea would probably require pushing the topic branch first so GitHub has the commit graph it needs and from there could find the nearest branch in the upstream repo (could be the same as the origin). Alternatively, X number of local commits could be send in a request but that seems rather clunky and gets complicated when following any merge commits if users were to git merge instead of git rebase.
Thank you for your patience, @heaths; with end of the year holiday leave and priorities, this is the soonest I've been able to follow up here.
Catching up on the discussion, here are some questions and comments:
I do think it makes sense to define our on gh-merge-base but fall back to checking for vscode-merge-base if gh-merge-base is undefined, or go through the algorithm to set gh-merge-base, agreed?
Is this comment alluding to GHPR extension that @alexr00 is involved with?
So rather than gh having awareness of Visual Studio code's implementation, VS Code would honor gh-merge-base before falling back to vscode-merge-base?
I'd also like to put this in cli/go-gh if that's okay - and if it still supports stubbing out mocks for testing in cli/cli. Could be useful to extensions, and there are already some git APIs mirrored there (and, oddly, duplicated in cli/cli).
Where are you thinking this lives within cli/go-gh?
what are next steps on this? Has anyone talked to the team that owns the GraphQL (or at least orchestrates the various features added to it) about the idea?
I haven't talked with either the Pull Request or Git Systems teams, who I imagine would need to be involved regarding the aforementioned REST or GraphQL changes:
Long term, I still think the algorithm for determining the target branch should actually be implemented in GitHub's GraphQL and/or REST APIs.
How much of a go / no-go is ☝ for beginning any work on this?
Unless @williammartin has, I'd posit any such API changes won't be prioritized to unblock this work, requiring us to work with the public APIs as-is to get this working and discuss with the teams. Just my $0.02
That's correct. So if nothing happened that we defined gh-merge-base, we could check vscode-merge-base if it exists.
IIRC, I meant that the target branch parsing should ideally go into cli/go-gh so extensions could use that information rather than parse it themselves. I imagine moving (or cloning) a lot of the branch parsing work cli/cli does now and put it next to pkg/repository or something. If it's even considerable, I can work up a more detailed plan unless you or someone has a better suggestion. But the idea would be to provide extensions branch information, which could be useful for scenarios like cleaning up after themselves if they make or merge a branch, need to send local branch info to the remote endpoint, etc.
Not blocking, but ideal. Anything that uses local branch information does not have an accurate picture. It might be accurate most times, but for various reasons I've created branches with different names locally and remotely (often times to push changes atop a local "clone" of a remote branch to a different remote branch from which to create a draft PR or something). It'll probably be fine 99% of the time, but only GitHub has the accurate picture for PRs including where the HEAD points for a given branch by the time the PR is created vs. when the topic branch was created.
I wonder how accurate for-each-ref and the reflog approaches are comparatively. If for-each-ref is sufficient then it would seem nice to use that because it could later be shifted in the API. On the other hand, the reflog is local only. On the other, other hand, it would be nice to use the reflog approach since it's probably been fairly well battle tested by VSCode.
That seems like it might be the first thing to test out to figure out a next step?
The is-base token is also fairly new and, AFAIK, gh doesn't currently explicitly depend on a specific version of git. Depending on how this is exposed, taking an implicit dependency (and, what, failing I guess?) in a common code path seems wrong. So, yeah, the reflog approach is probably safer. Could always "upgrade" one day.
Activity
heaths commentedon Jul 16, 2024
@williammartin @andyfeller what do you think of this proposal? Any other ideas? I'm working primarily against a feature branch currently and this keeps biting me again and again. Ideally, it's automatic but I appreciate that would be a breaking behavior change. Maybe something to consider for v3, though.
What would be nice is if GitHub implemented an endpoint / query to do this based on remote info since PRs are opened against your knowledge of remote branches (well, local to GitHub). Using the local branches is problematic because some people - like me - tend to prune which branches in a large mono repo are fetched. So the local client may not have the most reliable info.
I've played around with existing queries and found some ways to do this remotely, but it requires a lot of chatter with the GraphQL endpoint so it may not be the best solution for this (slow).
williammartin commentedon Jul 18, 2024
Hey @heaths, before talking about solutions I just want to make sure I understand the situation:
main--baseeach time is annoying?How do branch protections or rulesets come into the picture here?
So then your suggestion is that we could have an
--auto-baseflag that looks at the git history (ideally remotely) to determine the most likely branch that this PR should be opened against?heaths commentedon Jul 18, 2024
That's correct. I think we had talked about it in our meeting a while back, but it's been a while. It's not so much that passing
--baseis annoying, but that it's easy to forget and a few more annoying things fall out of that as a result:So cleaning up after forgetting is the annoyance...if people even notice.
andyfeller commentedon Jul 30, 2024
@heaths : if I understand your explanation, you're working on
feature-ain the following diagram wanting to targetdevelopfor PRs created rather thanmain.In this scenario, I can understand wanting to avoid wasted GitHub Actions runs and time spent because the wrong branches are targeted. Much less the other frustrations mentioned above, so I'm 👍 around the idea in general.
I would imagine having 1) a new command flag and 2) a new configuration option would allow people to try and enable the feature.
How many scenarios are we accounting for?
I can see several permutations:
I'd like to hear about any specifics on branch protections or rulesets involved as I normally assume this just blocks people from pushing commits to specific branches directly, requiring developers to jump through different but familiar hoops for opening PRs.
heaths commentedon Jul 30, 2024
I think whether the branch is local or not and from what commit it was branched is moot compared to what the PR should target. Because the action is to create a PR against the remote (i.e., GitHub), what it should target has to be remote. Now, that said, if the concern is that perhaps the dev forked from a branch that hasn't been pushed yet, but I'd imagine that's a pretty rare case and many of those times, it's probably more of a "placeholder" - a "temporary tag" to easily go back from and try a different angle. If that assumption holds true in many of those cases, then it still comes down to what remote branch on GitHub should be the target e.g.,
developin your diagram.In our case - and this may be uncommon, but plausible in other cases - our configured workflows and branches are different for
mainanddevelop(in your diagram; we call itfeature/track2but that's not important here). Significantly different, in fact, which is why it doesn't just waste agent time. If we switch the target branch later after jobs have already run, the workflows aren't rerun and we have to push a new commit (perhaps empty or just rebase HEAD) to get the right jobs to trigger.I do like the idea of some sort of configuration that could, perhaps, be stored on the branch much like your
gh-resolved = baseon remotes, or (I just found out)vscode-merge-baseon branches (for the GitHub Issues and Pull Requests VSCode extension, no doubt). In fact, maybe the CLI could even fall back to that since we're all one big happy family.Edit: case in point: Azure/azure-sdk-for-rust#1725
I once again forgot to set the
--baseand even after I switched to the right target viagh pr edit, I still had togit commit --amend && git push --forceto get the right checks to trigger.andyfeller commentedon Aug 7, 2024
We're both in agreement — PRs ultimately care about a remote branch to target — which I predict is typically the source of the branch whether created locally or remotely.
The questions were an attempt to capture more concrete, practical acceptance criteria on how
ghwill behave in various situations.Thank you for sharing the additional context! 👐
This scenario makes sense and is only an extension of how branch protection rules / repository rulesets are used.
Your suggestion of extending
ghawareness of VS Code configuration is not a bad idea.My general concern is understanding how VS Code sets this and how this relates to
ghworking. Depending on how stable and predictable it is, it could be an option.Do you have any more information you can share? Links?
I see this in code here but I was hoping for more information on how VS Code users trigger this behavior in the IDE.
heaths commentedon Aug 8, 2024
I can start a thread with the owners, or get them to reply here - whichever they prefer. I think it would be best if gh sets its own, but could see falling back to vscode's for this purpose only. Or maybe not. But at least having its own marker, gh could be configured separately for whatever reason devs may have.
heaths commentedon Aug 29, 2024
Are you still waiting on me to talk to the VSCode owners? I don't think that should be blocking as VSCode could separately choose to use it or not.
This is a near-daily issue for us.
14 remaining items
alexr00 commentedon Oct 10, 2024
VS Code's built in git extension doesn't know that GitHub exists as the git remotes could be non-GitHub, so we'll always want to compute the merge base there.
This seems reasonable! If this existed then I would say GHPR should always try to use this and fall back to what the built-in git extension provides if for some reason GH doesn't know about a merge base.
heaths commentedon Oct 10, 2024
Since vscode-merge-base is meant to be generic I can see not unifying but it might still be good for us to consider falling back to it if your algorithm is comparable. Could you summarize, or is its pretty straightforward in open source code?
alexr00 commentedon Oct 11, 2024
@lszomoru wrote the algorithm. It is open source though and it is here:
https://github.com/microsoft/vscode/blob/d1bab6b1abfb120036e85a13b0cff92590d37d3b/extensions/git/src/repository.ts#L1485-L1506
and here:
https://github.com/microsoft/vscode/blob/d1bab6b1abfb120036e85a13b0cff92590d37d3b/extensions/git/src/repository.ts#L1511
heaths commentedon Oct 11, 2024
Thanks, @alexr00! But now I feel bad because it seems @williammartin already found that. 🤦♂️
Given that
github-pr-merge-baseis deprecated (IMO, I agree it might be good to remove to avoid confusion) andvscode-merge-basedefines the algorithm @williammartin is fine with using, I do think it makes sense to define our ongh-merge-basebut fall back to checking forvscode-merge-baseifgh-merge-baseis undefined, or go through the algorithm to setgh-merge-base, agreed?@williammartin I'd also like to put this in cli/go-gh if that's okay - and if it still supports stubbing out mocks for testing in cli/cli. Could be useful to extensions, and there are already some
gitAPIs mirrored there (and, oddly, duplicated incli/cli).Open PR against gh-merge-base
Open PR against gh-merge-base
Open PR against gh-merge-base
heaths commentedon Dec 20, 2024
@andyfeller @williammartin what are next steps on this? Has anyone talked to the team that owns the GraphQL (or at least orchestrates the various features added to it) about the idea? Since the commit graph would have to be known, the best idea would probably require pushing the topic branch first so GitHub has the commit graph it needs and from there could find the nearest branch in the upstream repo (could be the same as the origin). Alternatively, X number of local commits could be send in a request but that seems rather clunky and gets complicated when following any merge commits if users were to
git mergeinstead ofgit rebase.andyfeller commentedon Jan 7, 2025
Thank you for your patience, @heaths; with end of the year holiday leave and priorities, this is the soonest I've been able to follow up here.
Catching up on the discussion, here are some questions and comments:
Is this comment alluding to GHPR extension that @alexr00 is involved with?
So rather than
ghhaving awareness of Visual Studio code's implementation, VS Code would honorgh-merge-basebefore falling back tovscode-merge-base?Where are you thinking this lives within
cli/go-gh?I haven't talked with either the Pull Request or Git Systems teams, who I imagine would need to be involved regarding the aforementioned REST or GraphQL changes:
How much of a go / no-go is ☝ for beginning any work on this?
Unless @williammartin has, I'd posit any such API changes won't be prioritized to unblock this work, requiring us to work with the public APIs as-is to get this working and discuss with the teams. Just my $0.02
heaths commentedon Jan 8, 2025
gh-merge-base, we could checkvscode-merge-baseif it exists.cli/go-ghso extensions could use that information rather than parse it themselves. I imagine moving (or cloning) a lot of the branch parsing workcli/clidoes now and put it next topkg/repositoryor something. If it's even considerable, I can work up a more detailed plan unless you or someone has a better suggestion. But the idea would be to provide extensions branch information, which could be useful for scenarios like cleaning up after themselves if they make or merge a branch, need to send local branch info to the remote endpoint, etc.williammartin commentedon Jan 8, 2025
I wonder how accurate
for-each-refand the reflog approaches are comparatively. Iffor-each-refis sufficient then it would seem nice to use that because it could later be shifted in the API. On the other hand, the reflog is local only. On the other, other hand, it would be nice to use the reflog approach since it's probably been fairly well battle tested by VSCode.That seems like it might be the first thing to test out to figure out a next step?
heaths commentedon Jan 8, 2025
The
is-basetoken is also fairly new and, AFAIK,ghdoesn't currently explicitly depend on a specific version of git. Depending on how this is exposed, taking an implicit dependency (and, what, failing I guess?) in a common code path seems wrong. So, yeah, thereflogapproach is probably safer. Could always "upgrade" one day.