Pull Requests
Just like forking, pull requests are a convention provided by Git hosting services, rather than a feature in Git itself. While there is a command git request-pull
, this is a different thing. GitHub and Bitbucket provide a pull request feature, while GitLab refers to a similar feature as “merge requests”.
A pull request is a way to ask for the changes in one branch (or any commit, really) to be integrated into another. The names come from the fact that, doing a pull request, we’re asking someone to pull from a certain branch to another, merging the branches.
In addition to the above, services provide a variety of features under the name “pull request”. Here are some examples:
- The creator of a pull request can often ask for a code review from other developers
- The interface for managing a pull request often allows for discussing the pull request
- The pull request author or someone else can push further commits to the branch to be merged, updating the pull request
You can certainly have a workflow with a single repository, doing your work in a feature branch and then making a pull request to merge that into the master
branch, for example. However, this means you need write permissions to that repository in order to push your feature branch to it. In a fork-based pull request workflow, you push the feature branch to your fork, then make a pull request asking for this to be integrated into the original repository.
A Practical Example
Let’s look at an example continuing on from where we left off last chapter. We had created a local clone of our fork and added the original repository as a remote called upstream
. Now, we will create and checkout a new feature branch. There are a number of ways to accomplish this in Tower… this time, let’s use the Cmd+B keyboard shortcut to bring up the sheet for creating a new branch, and name the branch “feature/header”:
Next, let’s make a change and commit:
Let’s say that at this point, the master
branch of the upstream repository gets updated. In the long run, we certainly want to keep our local clone updated, so any new branches can build on the latest code. Moreover, what if the upstream update touches the same code as the feature we are working on? For a variety of reasons, we may want to rebase our feature branch on the upstream master
branch. This is why we added the upstream
remote. Using this, we can checkout the master
branch of our clone, pull from upstream
, checkout the feature branch, and rebase that on the updated master
branch. I’ll start by checking out the master
branch by double-clicking it. I’ll then click the “Pull” button in the toolbar, and choose to pull from upstream/master
:
I’ll then checkout my feature/header
branch again by double-clicking it, then right-click it and select “Rebase on Revision…”, and keep the default selection of master
:
Now, my feature branch contains the latest changes from the upstream master
branch:
Let’s make another change and commit on our feature branch:
Finally, we’ll push our feature branch to our fork, to prepare for making the pull request. Again, this can be accomplished in several ways in Tower, but an easy one is simply dragging the feature/header
branch onto the origin
remote in the sidebar and dropping it:
I’ll choose to create an identically-named branch on origin
(my fork) and to have my local branch track the new remote branch:
Note the icon with an arrow and the number one next to the master
branch in the sidebar: at this point, the feature branch in our fork repository is up-to-date with the origin
remote, but the master
branch is not. I’ll double-click the master
branch and then click the “Push” button in the toolbar:
Now our fork has the latest versions of both the master
branch and the feature/header
branch. The next step is creating the pull request. Even though this is a service provided by GitHub, I can do this through Tower. I’ll begin by right-clicking my feature/header
branch in the sidebar, and selecting “Create New Pull Request from “feature/header”…”. The origin
remote — my fork, that is — is selected as the repository, but this is not where I want my code to go — I want my code to be pulled into the upstream
remote. To that end, I select the upstream repository as the target of my pull request, with the default selection of the upstream/master
branch staying as it is. Make sure that the head branch is origin/feature/header
— this is our feature branch on the fork, the one we want pulled into upstream:
The pull request has been created. While Tower can list pull requests, the one we just created does not show up here, as it targets the upstream repository, not our fork, which is the one we’re dealing with in Tower. However, we can view the pull request on GitHub, where we now see that the maintainer of the repository has commented on the pull request: we should format our code according to some guidelines:
No problem! We checkout the feature/header
branch and commit a fix:
Then, we push to the feature/header
branch on the fork:
Now, the commit shows up in the pull request as well:
The maintainer now decides to merge the pull request, hitting the “Merge pull request” button in GitHub. That’s it! The pull request page shows that my branch has been merged, and my code is now part of the original repository on GitHub. At this point, I can delete my feature branch.