Skip to content

Set default base branch for new PRs #8979

Open

Description

@heaths

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.

  1. 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.
  2. 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).

Activity

  1. heaths commented on Jul 16, 2024

    @heaths
    ContributorAuthor

    @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).

  2. williammartin commented on Jul 18, 2024

    @williammartin
    Member

    Hey @heaths, before talking about solutions I just want to make sure I understand the situation:

    1. There is a long-lived feature branch
    2. PRs should be going to that feature branch instead of main
    3. 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?

  3. added
    more-info-neededMore info needed from user/contributor
    gh-prrelating to the gh pr command
    and removed on Jul 18, 2024
  4. heaths commented on Jul 18, 2024

    @heaths
    ContributorAuthor

    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:

    1. The PR title is likely just the branch name because you likely have > 1 commit.
    2. 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.
    3. 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.

  5. added and removed
    more-info-neededMore info needed from user/contributor
    on Jul 23, 2024
  6. andyfeller commented on Jul 30, 2024

    @andyfeller
    Contributor

    @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.

    gitGraph
       commit
       commit
       branch develop
       checkout develop
       commit
       commit
       branch feature-a
       checkout feature-a
       commit
       commit
       checkout develop
       merge feature-a
       commit
       checkout main
       merge develop
       commit
       commit
    
    Loading

    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:

    1. whether the branch is created locally or remotely
    2. whether the branch is created from default branch, feature branch, tag
    3. 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.

  7. heaths commented on Jul 30, 2024

    @heaths
    ContributorAuthor

    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.

    Edit: case in point: Azure/azure-sdk-for-rust#1725

    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.

  8. andyfeller commented on Aug 7, 2024

    @andyfeller
    Contributor

    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.

  9. heaths commented on Aug 8, 2024

    @heaths
    ContributorAuthor

    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.

  10. heaths commented on Aug 29, 2024

    @heaths
    ContributorAuthor

    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.

  11. 14 remaining items

  12. alexr00 commented on Oct 10, 2024

    @alexr00

    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.

  13. heaths commented on Oct 10, 2024

    @heaths
    ContributorAuthor

    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?

  14. heaths commented on Oct 11, 2024

    @heaths
    ContributorAuthor

    Thanks, @alexr00! But now I feel bad because it seems @williammartin already found that. 🤦‍♂️

    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).

  15. self-assigned this
    on Dec 2, 2024
  16. added a commit that references this issue on Dec 9, 2024
  17. removed their assignment
    on Dec 16, 2024
  18. heaths commented on Dec 20, 2024

    @heaths
    ContributorAuthor

    @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.

  19. andyfeller commented on Jan 7, 2025

    @andyfeller
    Contributor

    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:

    1. 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?

    2. 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?

    3. 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

  20. heaths commented on Jan 8, 2025

    @heaths
    ContributorAuthor
    1. That's correct. So if nothing happened that we defined gh-merge-base, we could check vscode-merge-base if it exists.
    2. 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.
    3. 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.
  21. williammartin commented on Jan 8, 2025

    @williammartin
    Member

    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?

  22. heaths commented on Jan 8, 2025

    @heaths
    ContributorAuthor

    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.

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

    enhancementa request to improve CLIgh-prrelating to the gh pr command

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions