As developers who use GitHub, we use and love pull requests. But what happens when you only want part of a pull request?
Let’s say, for example, that we have a pull request with three commits. Unfortunately, the pull request’s author accidentally used spaces instead of tabs in the second commit, so we want to fix this up before we pull it in.
The main tool we’re going to use here is interactive rebasing. Rebasing is a way to rewrite your git repository’s history, so you should never use it on code that you’ve pushed up. However, since we’re bringing in new code, it’s perfectly fine to do this. The PR’s author may need to reset their repository, but their changes should be on separate branches to avoid this.
So, let’s get started. First, follow GitHub’s first two instructions to merge (click the little i
next to the Merge Pull Request button):
git checkout -b otheruser-master master
git pull git@github.com:otheruser/myproject.git master
Now that we have our repository up-to-date with theirs, it’s time to rewrite history. We want to rebase (rewrite) the last three commits, so we specify the range as HEAD~3
:
git rebase -i HEAD~3
This puts us into the editor to change the rebase history. It should look like this:
pick c6ffde3 Point out how obvious it is
pick 9686795 We're proud of our little file!
pick a712c2c Add another file.
There are a number of commands we can pick here. For us, we want to leave the first and last unchanged, so we’ll keep those as pick
. However, we want to edit the second commit, so we’ll change pick
to edit
there. Saving the file then spits us back out to the terminal. It’ll also tell us that when we’re done, we should run git commit --amend
and git rebase --continue
.
Internally, what this does is replay all the commits up until the one with edit
. After it replays that commit, it pauses and waits for us to continue it.
Now, we can go and edit the file. Make the changes you need here, then as it told us, it’s time to make amends:
git commit --amend
This merges the changes you just made with the previous commit (the one with the misspelling) into a new commit. Once we’ve done that, we need to continue the rebase, as all the commits after this one have to be rewritten to point to our new one in the history.
git rebase --continue
Our history rewriting is now done! It’s now time to merge it back in to master
, push up our changes and close the pull request. First we’ll need to switch back to master, then we can merge and push.
git checkout master
git merge otheruser-master master
git push
Congratulations, you just (re)wrote history!
For those of you who want to try this, I’ve made a test repository for you to work on. Try it out and see if you can fix it yourself!
Thanks to Japh for asking the question that inspired this post!