Git is my favorite version control system. And GitHub is where I love to keep my open-source projects. My most popular project is php-mode and it receives the most patches from other programmers. I can submit changes to a program on GitHub by sending a ‘pull request’ to the repository for that program. And when I receive pull requests I can merge them automatically with the click of a button.
But I never like using that button. Today I want to write about why and how I prefer to handle pull requests.
Why Not the Button?
Let’s say someone sends me a pull request with only one commit. If I use the GitHub interface to merge the pull request I will end up with two commits in my repository: one for the commit from the contributor, and one commit merging the first into the main branch of my repo. I do not like the unnecessary merge commit.
Furthermore I have no chance to test submitted code if I merge the pull request through GitHub’s interface. Testing is not an issue if the patch fixes something like documentation. I can read and confirm those changes on GitHub. But any changes or additions to code demands testing for quality assurance.
To avoid the wasteful merge commit and test the code I need to get a copy of the changes from the pull request into my local repository. There are multiple ways to do this. But I prefer the following:
Using Patch URLs
The git-am command applies patches to a repository. It expects the patches to be in a certain format designed for inclusion in email messages. This makes git-am useful for projects where people submit changes to mailing lists, such as Git’s own.
But we can also get patches in the same format on GitHub. And without having to deal with emails! Here is the full URL for the pull request from earlier:
We can get every commit in the pull request by adding
.patch to the end of this URL.
Now the patch is in the proper format for git-am. We can feed the patch directly into Git from the command-line with the help of the cURL program. Like this:
$ curl https://github.com/ejmr/php-mode/pull/67.patch | git am -s
This will apply the commit(s) to the current branch while also ‘signing off’ on each of them. That is the purpose of the
-s option for git-am. Projects use sign-offs for different reasons; for php-mode I sign-off on patches as an indication that I tested and reviewed the changes.
If the pull request contains more than one or two commits I like to make a separate branch for the pull request. Then I use the same method above to fetch and apply the commits. If the code behaves as expected I then merge that branch into my main
master branch. Here is an example using a pull request containing seven commits:
# Create a new branch for the commits, starting from 'master', and # change to the new branch. $ git branch haxney/ert-tests master $ git checkout haxney/ert-tests # Now fetch and apply the commits from the pull request. $ curl https://github.com/ejmr/php-mode/pull/62.patch | git am -s # Then run whatever is necessary to test the code. If everything # looks good then merge this branch into the master branch and send # the changes back to the main repository GitHub. $ git checkout master $ git merge --no-ff haxney/ert-tests $ git push origin master
Note: Some people never use
--no-ff and some people prefer to always use it. Read the git-merge documentation to help decide whether you want to use a ‘fast forward merge’ or not.
My repository will now include the commits from the pull request. But there is one more thing to do: close the pull request on GitHub. All that requires is clicking a single button, and that is one button I have no problem using with pull requests.