GitHub and Contributing to Pull Requests
I have a few projects up on GitHub, but it’s more of a “code storage” place than a “get work done” place. But the other night I ran across a project that I could make a quick contribution to. Besides helping out the project, I also learned a few things about how pull requests work. Including how to clone a pull request and work with the pull request author directly.
Background
I like blogging. I also like blogging software. It’s fun to poke around in the code and see what’s going on. I have local installs of both WordPress and Ghost so I can test things without breaking a live installation. The project that inspired this post was a pull request for the default Ghost theme Casper.
In this case, the current version of Casper introduced a navigation menu in the top right corner. If the blog owner has added navigation items in the admin panel, the menu shows up. The navigation menu replaces the RSS subscription button in the top right. The RSS button then moves into the navigation panel.
If there is no navigation menu, the old subscribe button doesn’t show up in the top right. This was what the pull request was attempting to solve. It got me curious about the code. So I started to dig into it.
Getting the Code
GitHub has several ways of getting the code to pull request. There are buttons that will open the pull request in the GitHub desktop software1 at the bottom of each thread just above the comment box.
I’m using the command line2 and the instructions provided don’t reflect the current state of the GitHub interface.
Even if the pull request is still active the instructions for an inactive pull request work just fine—provided you have write access to that repository. But if the pull request is to a third-party repository, there’s a few other steps needed.
In this case, I forked the Casper repository on GitHub. Then I cloned it to my laptop.
$ git clone https://github.com/JenniferMack/Casper.git
Notice I’m cloning my fork, not the main Casper repository. I don’t have write access there. This way I can push my changes back to GitHub. But this repository is now in my own little world and doesn’t reflect changes made in the main repository. This is fixed by adding the main Casper repository as an upstream
.
From inside the new Casper
folder do:
$ git remote add upstream https://github.com/TryGhost/Casper.git
Now I have two remote repositories linked to my local one.
origin
: This is my repository on GitHub that I have write access to.upstream
: This is the main repository on GitHub that I have read-only access to.
The upstream connection is needed to keep track of changes in the main repository. It also provides the link so I can get the pull request we’re interested in. We change origin
to upstream
in the provided commands, and provide the pull ID.
$ git fetch upstream pull/ID/head:BRANCHNAME
The command I used was:
$ git fetch upstream pull/191/head:pull-191
Which created a new branch (pull-191
) in the repository on my laptop. This lets me play with the code, but I can’t put my changes back on GitHub yet. The branch pull-191
only exists on my laptop. So I have to create that branch first. This is done with the push command and the –set-upstream
option.
$ git push --set-upstream origin pull-191
Now if I go to my GitHub page, I’ll have a new branch there.
A Pull Request for a Pull Request
Now that I’m set-up, I can make changes to the code locally. Once I’m happy with my progress, I can push those changes to my GitHub repository. But it’s just sitting there—no one will know about it unless I tell them.
On GitHub, you communicate with pull requests. Once one is made, a conversation can form around it. It’s a bit confusing at first, don’t get discouraged.
Remember we created a branch from a pull request and worked on it locally. But we want to tell the author of the original pull request about our changes. Not the main project. We don’t want to create another pull request, there’s already one present. We’re just building on the existing work.
To create the pull request in the right place, we need to know two things:
- The pull request author’s repository.
- Which branch the pull request was based on.
For the Casper changes the pull request author’s repository is keiga-san/Casper and the branch is subscribe-button. Find this out by looking at the top of the pull request page.
The names aren’t clickable. You’ll have to manually navigate to the authors page. Once there, you’ll see a message with a big green box.
This will take you to the page to create a pull request. Change the drop-downs so you’re looking at the right branches, add a comment, and create the pull request.
Now the pull request author can look at the changes, and either ask questions, merge the changes, or reject them. For this project we exchanged a few messages before my changes were merged in.
Ok so my changes are now in keiga-san’s repository. But what about getting them to the main project?
That part happens automatically!
The original pull request is linked to a specific branch. If that branch is updated. The changes can be seen by the main project. When keiga-san merged in my changes, that update migrated to the main repository. Scrolling to the bottom of that pull request you can see my commits—even though I never directly worked on the main pull request.
I think that’s pretty cool.
Once you’ve done this once, it’ll make a lot more sense. But don’t let it intimidate you. This is how code gets done.
- Download for Mac or Windows. ↩
- With TotalTerminal I have a terminal window when ever I need one. It’s faster than using another app. ↩