The Art of the Pull Request
The Art of the Pull Request
There is little argument that GitHub has revolutionized the way open source projects are managed. Gone are the days of hunting down a project’s maintainer and negotiating needed changes in the hope that your email with attached patch file was accepted into the master branch (although some projects still require such pomp and circumstance). This generally opaque process was replaced by GitHub’s fork + pull request model. You might say that git itself contains a robust pull request system but GitHub added the special social sauce and dead-simple pull request generation system making it the lingua franca of the open source community.
With all the social bells and whistles GitHub provides I still strive to be as “close to the code” as possible and found it frustrating that I was being pulled into the browser every time I wanted to determine if a pull request would pass muster. Visiting the page for a pull request you’re greeted with an assortment of information.
There are nice shiny buttons to merge and comment on the request but the page is arguably the most important bit of information I need to determine if I want to accept the request – the code I run to merge this change into my branch. After pulling my hair out for while trying to find this information I broke down and decided to RTFM. According to the GitHub docs you can view the code to merge the changes by clicking on the teeny tiny (i)
icon on the merge bar.
Nevermind that other icons on the page have no clickable action and there is no indication to suggest that this icon, gatekeeper of the page’s most important line of code, would be actionable.
Desperate for a better alternative to GitHub’s hidden code boxes I scoured the internet for a way to view pull requests on the command line. I ultimately found the answer from a more human source, @glasser who manages the myriad pull requests at Meteor. By adding a magical line to your .git/config
you can merge pull requests to your heart’s content.
.git/config
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@github.com:gleitz/howdoi.git
Add the following code above the fetch = +refs...
line:
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
Your code block should now look something like this:
[remote "origin"]
fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@github.com:gleitz/howdoi.git
You can now fetch your pull requests with:
$ git fetch origin
From github.com:gleitz/howdoi
* [new ref] refs/pull/24/head -> origin/pr/24
* [new ref] refs/pull/26/head -> origin/pr/26
* [new ref] refs/pull/30/head -> origin/pr/30
* [new ref] refs/pull/31/head -> origin/pr/31
...
And check out a particular pull request with:
$ git checkout pr/24
Branch pr/24 set up to track remote branch pr/24 from origin.
Switched to a new branch 'pr/24'
As a final protip you can do the following to check out a pull request in a “detached head” state. This won’t create a local branch and will keep your local git repo more clean:
$ git checkout origin/pr/24
Note: checking out 'origin/pr/24'.
You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at de92b36... adding initial coloring to howdoi, better lexer selection to come
Happy coding!