IvanTse

My journey to better programming and beautiful code

GitHub References

Aug 17, 2014 | 4 minutes read

There are two special types of references that are available in your GitHub repository. GitHub creates these references for each pull request; they are pull/:id/head and pull/:id/merge. Let's take a look at them and how they can be useful.

Pull Request Head

GitHub automatically stashes all the changes for a pull request against the main repository. And this head reference points at the latest commit. Why does GitHub do this? Well, when the requester deletes his/her fork, one might think that the changes are also lost. However, this is not true. You are still able to merge the pull request because those changes are "saved" in the reference. Nothing is lost!

In addition, you can checkout the pull request locally without needing to add a remote refspec. This is extremely helpful when there is a stale pull request that conflicts with master and the remote repository has been deleted. You would simply modify it locally before merging.

One of the ways I use this reference to improve my workflow is that I can do a comparison across pull requests on a project. Sometimes, a massive project can be broken into two pull requests where one includes the other. That is, the successive pull request depends on the work done in the previous one. I would code review the first one and give it a :+1:. But when, I review the second pull request, the diff on GitHub includes changes from both pull requests. This is not ideal because I want to see changes that were made specifically for the second pull request; the commits that I haven't seen yet. With head references, I can make this view by constructing a GitHub compare link between those two references. Here is a quick demonstration of this: #8 works on top of #7 but the compare link only shows the commits made in the second pull request.

As a side note, just as you can hide whitespace diff with git diff -w or git diff --ignore-all-space on the command line, you can add ?w=1 to the URL to get the same effect with the GitHub view. There are some other useful GitHub secrets you should check out.

Another way I used this functionality is extending the concept of checking out a pull request locally. @princesspretzel, who came up with this idea initially, wanted to be able to open all the files corresponding to a pull request. There are two use cases for this feature:

To achieve this, we can ask the GitHub Pull Request API to get a list of modified files for a pull request. Afterwards, we can checkout locally using pull/:id/head which allows us to see the changes in the editor (the pull request might have added new files). The last step is to simply invoke the text editor to open those modified files. We are currently working on a sublime plugin that does just that and I've created this command in GithubTools, my collection of command line tools for GitHub.

Pull Request Merge

The pull request merge reference points to the merge commit between the pull request and the base branch. I believe that GitHub creates this commit to test the mergeability of the pull request. How can this reference be useful? Well, TravisCI uses it to get a copy of the repository as if the pull request has been merged. Then, it will run the tests against this working copy. If you look at this example, you can see the job runs git fetch origin +refs/pull/2762/merge: followed by a git checkout -qf FETCH_HEAD command.

Another hypothetical use case for this reference is checking mergeability. You can determine mergeability by using the API but we can do this programmatically without the API call. One could fetch both the pull request head and the pull request merge references and determine if the latest sha in the pull request is in the history of the merge commit. The pull request is mergeable if so and not mergeable otherwise. I am planning on testing this out and implementing it in GithubTools.


Let me know if you know of any other ways of using GitHub's special references for creating a better workflow. Here are some external links that you definitely should check out:

comments powered by Disqus