Skip to content

Dedicated pull request branches

Andrew Zipperer edited this page Apr 27, 2024 · 10 revisions

This page provides instructions on how to quickly create a dedicated branch before creating a pull-request and why we ask you to do so.

Magit’s PULL_REQUEST_TEMPLATE which is shown when you create a new pull-request, links to this page. Feel free to link here from the PULL_REQUEST_TEMPLATE of your own repositories.

Creating a feature branch upfront using Magit

Press b c to create and checkout a new feature branch. Then make changes and create commits.

Creating a feature branch after committing to main using Magit

If you have already created commits before creating and checking out a feature branch, either because you forgot to or on purpose, then press b s to spin-off a new feature branch.

This command creates and checks out a new branch starting at and tracking the current branch (in our case main). That branch in turn is reset to the last commit it shares with its upstream. It is a bit more complicated than that and if you want to learn more, then please consult the manual, but basically it turns this situation:

[HEAD -> main] Improve new feature
New feature
[origin/main] Some old bugfix
Initial import

into this:

[HEAD -> feature] Improve new feature
New feature
[main] [origin/main] Some old bugfix
Initial import

After you have done this, you can push the new branch using P p as usual. Finally restart the process of asking for your changes to be merged.

Creating a feature branch using Github

If you do not have access to Magit then you can also create a new branch on Github.

Go to your fork’s entry page and click on the Branch: main button and type the new branch name into the text field that appears.

Benefits for the contributor

If you push a new feature branch, then a yellow box with a green button is displayed on your fork on Github.

new-feature (less than a minute ago)            [Compare & pull request]

Click on Compare & pull request and you are back to the page used to create a new pull-request, from which you were previously sent here.

If you pushed your changes to your main branch on the other hand, then you have to go to the upstream repository, click on Pull Requests, click on New pull request, click on compare across forks, click on head fork: magit/magit, locate and click on your-fork/magit, and click on Create pull request. I am guessing that Github intentionally makes this so cumbersome to encourage users to always use dedicated feature branches for pull-requests. But apparently it is not cumbersome enough.

Benefits for the maintainers

When using Magit, maintainers can quickly check out a pull-request by typing b f. Unlike Git aliases that can be found in the wild this does not just create a branch, it also configures it properly. Among other things, the local branch has the name chosen by the contributor, the fork is added as a remote, the upstream is set to the branch against which the pull-request was created, and the push-remote is set to the fork.

(Furthermore other commands have been taught about branches created that way. magit-branch-delete knows that it might be appropriate to also delete the fork remote after merging the pull-request. magit-merge-into and magit-merge-absorb are also aware of pull-request branches.)

Unfortunately it is not possible to use the branch name “chosen” by the contributor when that is main. A branch by that name already exists in the maintainer’s local repository, so pr-NUMBER has to be used instead. Because the mechanism provided by Git to configure the push-target only allows configuring the remote itself but, unlike for the upstream, not the remote branch; the name of the branch that P p pushes to is always the same as the name of the local branch. Because the maintainer cannot push to a random new branch on a fork, the fork cannot be used as the push-remote, so the upstream repository is used instead.

The result is that the maintainer cannot easily see whether the contributor has pushed further commits (they won’t appear in Unpulled from {push-target} and then easily pull them (F p won’t work). Likewise the maintainer cannot push any commits to the push-remote branch; instead s/he has to push them to origin/pr-NUMBER and then instruct the contributor on how to deal with that.