Utility to Fetch GitHub Pull Requests

Update: You can fetch pull requests without using a script like the kind described in this article. See the use of git fetch in this article for details.

I publish the source-code for a lot of my programming projects on GitHub. Sometimes I am fortunate enough to receive pull requests for said projects. I use the word ‘fortunate’ because personally one of my favorite aspects of open-source development is when someone spends their personal time to contribute to and improve one of your projects. Personally I receive the most pull requests for PHP Mode, and so I have a simple script for Git which I use to fetch those pull requests, which I want to share today.

github-cpr.pl

Here is the Perl script I wrote, github-cpr.pl:

#!/usr/bin/env perl

use v5.14;

my $id = shift @ARGV;
my $remote_url = qx(git config --null --get remote.origin.url);

$remote_url ~~ /.+?github.com:(.+)\.git/i;

my $pull_request_url = "https://github.com/$1/pull/$id.patch";
my $branch_name = "github/pr/$id";

qx(git checkout -b $branch_name);
qx(curl $pull_request_url | git am -s);

__END__

I use the script as part of a Git alias:

git config --global alias.cpr "!perl /home/eric/Scripts/Git/github-cpr.pl"

Now if someone opens a pull request on a project I can fetch the commits for that pull request with the command git cpr 98, where the number is assigned by GitHub.

The Details

The URI for pull requests on GitHub looks like this:

https://github.com/ejmr/php-mode/pull/98

That number at the end is the argument which I give to the script. The script also makes the assumption that my repository’s origin remote matches the $remote_url regular expression from the script. That regular expression has one capture group: it grabs my username and project name from the URL. So in the example URL above it captures the ejmr/php-mode portion; I do not assign this to a separate variable in the script but simply reference it as $1.

Using that and the pull request number the script builds the $pull_request_url string. Note well that it suffixes .patch to the URL. If we add that to the end of a pull request URL then GitHub will return the pull request content in a format we can feed directly into the git-am command, which is exactly what the script does.

However, before applying the commits of the pull request, the script will create and checkout a new branch, forked from the current branch. This is the origin of the name cpr: ‘checkout pull request’. That branch will have the name github/pr/98, using whatever number GitHub gave to the pull request.

So after running the command I will find myself on a new branch with all of the patches from the pull request. From there I can test and review them, deciding whether to merge them or if I need to ask the contributor for additional feedback. Note that my script uses the -s option with git-am; this adds a Signed-off-by line with my name to each commit in the pull request. Personally I prefer to sign-off on commits as a way of indicating that I reviewed and tested the patches, like so.

And That’s It

There is not much to the Perl script so I hope that explained everything, but if not please don’t hesitate to ask. If you get pull requests for GitHub projects then you may find this useful, and if so I’d love to know and would happily welcome any improvements. If you have a different way you prefer to handle pull requests then I’d enjoy hearing about that as well. Git certainly allows for different workflows and I’ve found it educational over the years to listen to how other people manage their repositories.

Advertisements

One thought on “Utility to Fetch GitHub Pull Requests

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s