Reverse a git pull request on GitHub the hard way· 3 minute read
As you may know I am currently the maintainer of both Idiorm and Paris; well recently I merged in what looked to be an innocuous pull request from a contributor. Unfortunately this merge had unintended consequences and basically broke the backwards compatibility of the library. Shame on me!
After waiting for a patch that would fix the problem and coming up short I decided enough was enough. So today I backed out the errant merges in both Idiorm and Paris.
Now it is important to note here that both repositories had commits and merges in their history post the introduction of this rogue pull request. In addition these changes had been out in the wild for quite some time.
With this in mind it would not be possible to simply amend the previous commit, rebase the changes or reset to a previous commit. These would either break the history or in the case of amend simply be impossible as HEAD had moved on.
To do this I used a technique that I could find little reference to online - a reverse patch application. This is actually very simple with GitHub as you can use an equally unknown feature to obtain a patch file from a pull request.
You can go to any commit or pull request in the GitHub web interface and append .patch onto the end of the URL. This will then spit out the full raw commit or pull request as a pull request patch file.
For example if you have a pull request at https://github.com/user/project/pull/123 then you should access https://github.com/user/project/pull/123.patch to gain access to the aforementioned patch file. So either download this via your web browser or use wget on the command line.
We can now use git to reverse apply the patch:
git apply -R 123.patch git status
You will now see that the files affected by the patch are in a modified state and you can commit them in just like you would any other commit or patch application.
Once committed you can push the changes to your projects GitHub project without worrying about breaking its commit history or angering other contributors! This technique can of course be used with any git patch file and not just those obtained via GitHub.
This is not THE way to do this, but the hard way. This is more of a post to expose these two features as they are not so well known. You would of course usually perform this task using
git revertwith the merge commit. There are tonnes of posts out there about that though so what would be the fun in that!