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.
Get our popular Git Cheat Sheet for free!
You'll find the most important commands on the front and helpful best practice tips on the back. Over 100,000 developers have downloaded it to make Git a little bit easier.
As the makers of Tower, the best Git client for Mac and Windows, we help over 100,000 users in companies like Apple, Google, Amazon, Twitter, and Ebay get the most out of Git.
Just like with Tower, our mission with this platform is to help people become better professionals.
That's why we provide our guides, videos, and cheat sheets (about version control with Git and lots of other topics) for free.