How to create and review a GitHub pull request

by Michael Ernst

March, 2017
Last updated: March 23, 2017

The main way of contributing to an open-source project that is hosted on GitHub is via a pull request. A pull request says, “Here are some changes that I have made in my copy. Please incorporate them into the main version of the program.”


(Also see Version control concepts and best practices.)

Preliminaries (setup)

Start on a unit of work

When you are ready to start on a unit of work, such as fixing a bug or implementing a feature, create a branch. A branch is a parallel thread of development — you can create as many branches as you want in your repository, which is like having multiple independent repositories.

To create a branch named MYFEATURE and switch to it, run

git checkout -b MYFEATURE

(Use a descriptive, readable name for your branch, such as unicode-support or fix-issue-22.)

You can switch to an existing branch by executing a command such as

git checkout MYBUGFIX

When you commit changes (with git commit) or push commits to GitHub (with git push), they are saved to the current branch. The main, default branch is named master, but you won't work on the master branch. (If you were to work on the master branch, then after your pull request is accepted you would need to delete your fork and create a new fork, which would be a hassle.)

Each branch should represent a logical unit of work. If you are doing two different tasks (or if while doing a task you discover a second, distinct task), then create two different branches for them. This is a bit of a hassle for you, but it makes reviewing your changes much easier, and the maintainers will be more likely to accept your changes.

Committing and pushing changes

Before you start to implement your changes, write tests that currently fail but will pass once you have fixed the bug or implemented the feature. Run the tests locally to confirm that they currently fail. (The project's developer documentation will tell you how to do this.) Now, commit the tests and push them. Check that Travis CI has run the project's tests on your fork and that they failed.

Now, do your work, testing locally and committing logical chunks of work as you go. You can push these commits to GitHub by running git push whenever you like. Eventually, you will be done and ready for a code review.

Being done requires at least the following:

Pull upstream into your branch

Periodically pull upstream into your branch; that is, incorporate into your branch any work that other maintainers have done since you created your branch. It's easier to do this frequently than all at once. Here are two ways to do so:

git pull upstream BRANCHNAME
git pull

If this command had any effect, then:

Creating a pull request

Once you are happy with your work and you believe it is ready to be incorporated into the project's main repository, you can create a pull request.

  1. Update your branch from upstream.
  2. Ensure that your fork passes all tests both locally and on Travis CI.
  3. On your fork's GitHub page, click on “New pull request”, which appears just above the list of files.
  4. The last dropdown box is by default “compare: master”; change that to your branch. Wait a moment until GitHub shows you the changes, then review all of them (you will need to scroll to see them all).
  5. If there are any changes that are not related to main topic of your branch (or gratuitous whitespace/formatting changes), then don't make the pull request. Instead, go back to your working copy on your computer, undo those changes, and commit. Then start over to make the pull request, with a smaller and cleaner set of changes.
  6. Click “Create pull request”. Give a descriptive title, and write a paragraph that explains what you have done. If your pull request fixes any issues, then the paragraph should include the text “fixes #NNN”; this links your pull request to the issue and automatically closes the issue when your pull request is accepted. Finally, click “Create pull request”. This signals that you believe your code is ready for review.

Responding to review feedback

  1. You will receive feedback on your pull request. Respond to the feedback by making changes in your working copy, committing them, and pushing them to GitHub when the tests pass locally.

    As soon as you receive feedback, you can start working on it. The reviewer might not explicitly send you a message, and might forget to assign the code review back to you, so don't wait for those events.

    Make sure you are working on the right branch; use git branch to check. Never force a push with git push -f; doing so is bad practice in general and will corrupt your pull request.

    If you do what a code review comment suggests, you don't have to respond to that review comment in the GitHub code review system by saying "I did that". You only have to respond if more discussion is needed, such as giving information about why you disagree with the suggestion. If the code review asks a question, then usually the best way to answer it is by improving the documentation. Answering it in the code review will not help other programmers who read your code later, after it has been merged.

    When you push commits to GitHub, the pull request will be automatically updated. If you change a line of code on which you received feedback, that feedback is no longer shown by default. That is, GitHub assumes that if a line near a review comment has been changed, then the review comment has been resolved. This means that you should try not to push changes (such as a change to indentation) that change a line without addressing all the comments related to that line.

  2. After you have addressed all the review feedback, explicitly request a re-review. Don't assume that person will know when you are done. Use the pull request's GitHub webpage to request a re-review from the person who gave the original feedback. You can do this by adding that person as a reviewer — this works even if that person has reviewed the pull request before. You can also assign the pull request to that person, using the "Assignees" list in the right column of the webpage's "Conversation" tab. And, you can also write a comment in the conversation in the GitHub pull request.
  3. There will often be several rounds of feedback and fixes. The reviewer needs to approve your changes, and there may have been parts of your pull request that didn't make sense or that the reviewer was otherwise unable to review on the first iteration. You aren't done until the reviewer has approved your pull request. (Sometimes, multiple people will review your pull request, but it is most efficient to have them do their reviews one at a time rather than concurrently.) Remember to periodically update your branch from upstream.
  4. Eventually, your pull request will be accepted and your changes will be part of the project. Congratulations!
  5. Delete your branch, which no longer serves any purpose. (This may not be necessary: the person who merges your pull request may delete the branch for you.) This is usually easiest to do from your fork's GitHub webpage. You may periodically run git remote prune origin in your working copy to remove from your clone branches that have been deleted from the remote repository, so that you don't accidentally use them.

Some Git documentation recommends rebasing, amending commits, or other changes to existing version control history. Don't do any of these things. They are confusing and error-prone, they can corrupt your pull request, and they are not necessary. All of your changes will be squashed and merged into a single commit when your pull request is accepted, so don't worry about what the version control history of your branch looks like. Just focus on its differences from the upstream's master, which you can see in your pull request.

You will receive email about comments to your pull requests. Don't reply by email. Instead, reply on the GitHub webpage that is referenced by the email. One reason is that if you reply by email, you may needlessly bloat your response with all the quoted text from the email you received. Another reason is that if you reply by email, GitHub may not associate your comment with the right thread in the code review.

Reviewing a pull request

This section is for maintainers who are reviewing and merging a pull request.

This section is currently incomplete, but contains a few tips.

Merging the pull request

When a pull request is ready to be merged, it may consist of many commits. Future maintainers will not be interested in each individual commit, only in the overall feature — this is also what you have seen while you were reviewing.

To keep the version control history clean, select “Squash and merge” when you merge a pull request. This results in a single commit that contains the entire pull request. The default commit message is the concatenation of the messages for all the commits in the pull request, but this information is not useful to future developers. Therefore, edit the commit message. Usually the very first commit message, or the pull request's title and description, make a good commit message for the entire pull request.

Back to Advice compiled by Michael Ernst.

Michael Ernst