Chapter 4. Collaboration
In this chapter weâll start by looking at how to collaborate on a repository that you donât have permission to push to by creating a fork and a pull request. While forks are a good way to accept contributions from people you donât work with regularly, they are a bit too cumbersome for everyday use in a team that is working together closely. Because of this, later in the chapter weâll look at how to collaborate directly on a single repository without using forks. Lastly, weâll take some time to look more deeply into collaborating using pull requests and issues.
Contributing via a Fork
If you want to contribute directly to a repository, you either need to own it or have been added to it as a collaborator. If you want to contribute to a repository that you donât own and are not a collaborator on, youâll need to make a copy of it on GitHub under your user account. That process is called forking. Once youâve forked a repository, youâll be able to make any changes you want to your fork (copy) and youâll be able to request that your changes get incorporated into the original repository by using a pull request. Letâs go through that process now.
Go to https://github.com/pragmaticlearning/github-example. Click the Fork button in the top-right corner of the page, as shown in FigureÂ 4-1.
When you click the Fork button, if you are a member of any organizations, youâll see a list of all of the organizations youâre involved with as well as your username. Youâll be asked where you want to fork the repository (as shown in FigureÂ 4-2).
After you select where you want to fork the repository, or if you are not a member of any organizations, youâll be taken to your new repository page. Once youâve forked the repo, you can make any changes you want to your fork (copy). In the next section weâll look at how you can add a new file, like we did in ChapterÂ 3, and then how to create a pull request to try to get your change incorporated into the original repository.
Adding a File
In this section weâll look at how to add a new file to a repository. As a reminder, you can see in FigureÂ 4-3 that there are a collection of buttons on the right side of the screen above the listing of files, one of which says âCreate new file.â
Click this button and youâll be taken to the same new file screen as before, shown in FigureÂ 4-4.
Toward the top of the page is a text box just to the right of the project name, where you can enter the name of the file you want to add to the project. Below that is a text area where you can enter the content youâd like to put in the file. Scroll down the page when youâre done naming the file and entering the content; as shown in FigureÂ 4-5, youâll see a couple of text boxes where you can create a (required) short description and an optional extended description of the change that youâre making.
These descriptions will be saved as the commit message for your commit. If you donât enter anything, the default commit message will be âCreate (<filename>).â As mentioned in ChapterÂ 3, youâll want to enter a meaningful commit message so other people viewing the project will understand what you did and why you did it. As shown in FigureÂ 4-5, you have two options for where to commit this change: directly to the
master branch or on a new branch to propose the change as a pull request. Weâll start a pull request another way in a moment, but this âquick pull requestâ flow exists for immediately starting a pull request from your edits. For now, click the green âCommit new fileâ button: your new file will be added to the project and your commit will be added to the commit history. You can see in FigureÂ 4-6 that first-file.md has been added to the list of files.
Creating a Pull Request
Youâve made a change to your fork of the project, but the change hasnât propagated back to the original project yet. That makes sense. Anyone can fork any public project, and the project owner wouldnât want just anyone editing all of their files. However, sometimes itâs great to allow other people to propose changes to a project. This allows a large number of people to easily contribute to an open source project or a smaller team to work together on an internal project. That is what pull requests are for. Some maintainers send pull requests to their own repositories for the sake of documenting how theyâve developed their projects, even if theyâre not waiting for anyone elseâs approval! Many more approaches to maintaining, contributing, and working with open source software in general can be found at https://opensource.guide.
With a pull request, you can request that changes youâve made on a fork be incorporated into the original project. Letâs go through the process now. As you can see in FigureÂ 4-7, at the top of the page thereâs a âPull requestsâ tab.
Click the âPull requestsâ tab, and youâll see a screen similar to FigureÂ 4-8 showing that currently you donât have any outstanding pull requests. Click the green âNew pull requestâ button at the top right of the screen.
When you click the button, youâll see a screen similar to FigureÂ 4-9.
One of the first things youâll see in FigureÂ 4-9 is that it is proposing a pull request between
brntbeer:master. Pull requests are requests to incorporate the changes from one branch (stream of history) into another. In this case, GitHub has correctly guessed that I want to take the change that I made on the
master branch on my fork (the new file I added) and have that merged back into the
master branch on the original project that I forked from. Note that the branch with the changes that you want merged in is on the right, and the target branch youâd like it to be merged into is on the left.
As you look lower down in FigureÂ 4-9, youâll also see that it provides a summary of the changes that would occur if that pull request was mergedâI did indeed make one commit that changed a single file. It even shows in green the new content that would be added to first-file.mdâthis is often called the diff or difference. If I click the Split or Unified button, it will change the way in which the difference that is being proposed is rendered. This setting is âsticky,â meaning that GitHub will remember it for future diff renderings.
Once youâve confirmed that the proposed pull request is the one you want to create, the next step is to click the large green âCreate pull requestâ button. Doing so will take you to a page similar to FigureÂ 4-10.
This screen is your chance to tell the story and start a conversation about why your changes should be incorporated into the other project, so take the time to create a meaningful title and description of the changes youâve made. By default the title will be the first line of your commit message for your most recent commit, and if youâve made more than one commit on the branch youâre trying to have merged, the description will contain a bulleted list of the first lines of all of the commit messages that are part of the pull request. Thatâs a fine starting point, but youâre going to want to take a little bit of time to describe not only what changes youâve made, but why you made them and why theyâd be a good addition to the project. Since this is the start of a conversation, itâs often best to @mention (pronounced âat-mentionâ) the maintainer to ensure they see your request, and to let them know if you still have some changes youâd like to make or not. If youâre lucky, the repository youâre contributing to will have made use of an issue or pull request template to fill in some information or give you some instructions on contributing. For more information about these templates, please see the GitHub documentation.
You may also notice the âAllow edits from maintainersâ checkbox below the description section, to the left of the âCreate pull requestâ button. This allows the maintainers to make changes directly on your branch. This may sound scary at first, but it really helps the maintainers, and you, if there are small changes to be made before accepting your changes. Sometimes there may be simple stylistic changes or complicated changes that are easier for them to do to finish the pull request. If you donât select this option here, it also can be turned on or off from the pull request screen after the pull request is created.
Once youâve finished describing your pull request, click the âCreate pull requestâ button and youâll see a page that looks like FigureÂ 4-11.
There are a couple of things that you should notice in FigureÂ 4-11. First, notice that youâre now in the original project, under
pragmaticlearning. This makes sense. You wanted to create a request to pull your work into that project, so the pull request is part of that projectânot your fork. You can see that âbrntbeer wants to merge 1 commit into
brntbeer:master,â and it shows you the pull request (title and description) followed by the commit that was made. Clicking that commit displays the details of the commit in a review workflow, as you can see in FigureÂ 4-12.
Notice that the commit link has taken you to the âFiles changedâ tab of the pull request. This tab is where you can see all of your proposed edits for this pull request. However, in this situation you see just that one commit because thatâs what you clicked on. This is a useful review workflow when you want to jump through some work one commit at a time. Weâll cover code reviews for pull requests in more detail later in this chapter.
Going back to the pull request in FigureÂ 4-11, youâll see that there is an option to merge the pull request. That option is visible only to the owner of the project or to anyone the owner has added as a collaborator with âwriteâ or âadminâ permission. If someone without those permissionsâfor example, yourselfâwas looking at the page, he would not be able to merge the pull request. To illustrate, in FigureÂ 4-13 Iâve logged in as another user. When I view the same page, I donât get the option to merge in the pull request, although I can still comment on it if I want.
Often there will be a discussion before a pull request is merged, but weâll look at that more later in this chapter. For now Iâm just going to accept the pull request and merge it in. Clicking the âMerge pull requestâ button adds a text box where I get the option to customize the commit message for merging the pull request, as shown in FigureÂ 4-14.
Once Iâve made any changes I want to the merge commitâs message, I can just click the âConfirm mergeâ button below and to the left. The pull request is then merged, and the output is displayed, as in FigureÂ 4-15.
Notice that you can still see the pull request message and the commit, but now you can also see who merged in the pull request and approximately when they did so. I also have the ability to revert this pull request if the merge was done in error. The Revert button here will allow me to open a new pull request that does the inverse of the work I just did. Finally, if you look at the project page in FigureÂ 4-16, youâll notice a couple of things.
First, first-file.md has been added to the project. Second, there are 10 commits now in the original project. Clicking the â10 commitsâ link shows why (see FigureÂ 4-17).
In addition to the eight original commits in the project, there is the âCreate first-file.mdâ commit that was made on my fork and a new merge commit that brought the work into the original project when I merged the pull request. By default, whenever you merge a pull request, it will create one of these merge commits (it is possible to configure the repository to have different functionality, but weâll leave that as an advanced topic for you to learn about later). They are really useful because the commit message, which you can edit when you merge a pull request, allows you to document why you decided to include the work.
If you ever wanted to get rid of all of the work you merged in from a pull request, you could ask one of your developers to ârevert the merge commit for that pull requestâ and sheâd be able to easily remove all of the changes that got merged in. If you have permission to merge the pull request, you will also have the ability to bring in the changes by squashing them all together before merging, or rebasing before merging. These are more advanced workflows that we wonât be covering in this book. If you are interested in learning more, you should check out the GitHub learning resources.
Committing to a Branch
Now that weâve seen how to contribute via a fork, weâll look at a more common team-based workflow: committing directly to a repository that you have access to push code directly to. To some people, this workflow may seem like a combination of working on a fork as well as working on your own repository, with one exception: feature branching. In Git, everything is committed onto a branch, and the branch weâve done all of our commits on so far has been
master. An alternative to committing to
master is to create a branch that is often named after what youâre working on. Sometimes this is something simple, like
update-readme-with-contact-info, and other times itâs named directly after a work item thatâs been assigned to you by a project management team, like
Besides allowing you to work safely and experiment on changes without affecting the
master branch (which often signifies the safe, nonbuggy, stable code base), feature branching allows you to start a pull request in the same repository youâre in. This is the part that is similar to the forking workflow. An example of the type of workflow you will be using is shown in FigureÂ 4-18; itâs called the GitHub Flow. Keep this image in mind as you dive in and experience it for yourself.
If I want to augment the README.md file, the first thing I should to do is create a branch. That way Iâll be able to keep my changes separate while Iâm working on them and can open my pull request later. To do that, I can just click the âBranch: masterâ drop-down, which lists the current branches in the project and provides a text box for entering the name of an existing branch or the new branch that I want to create (see FigureÂ 4-20).
If I create an
update_readme branch, as you can see in FigureÂ 4-21, GitHub automatically checks out that new branch. You can see this both on the Branch pull-down where the current branch is displayed, and in the browser URL bar: the address ends with tree/update_readme, signifying that weâre on the
The next step is to start to make changes on the
update_readme branch. Iâll edit the README.md file and commit the changes like weâve done a few times up to this point. As you can see in FigureÂ 4-22, I have only one commit on the
master branch, but if you look at FigureÂ 4-23, where Iâve changed the branch to
update_readme, in addition to the initial commit you can also see the new commit that I made on the
I might continue to work on the branch for a while, getting my changes just right. Once Iâm ready to get some input, Iâll want to create a pull request to start a conversation about my proposed changes.
Creating a Pull Request from a Branch
There are many ways to create a pull request, but as in the previous chapter, Iâll click the Pull Request tab on the top part of the page and then click the green âNew pull requestâ button. When I do this, as you can see in FigureÂ 4-24, the experience is slightly different. Now GitHub isnât sure what branches I want to create a pull request between, so I have to tell it.
On the left you can see âbase: master.â That is perfect as it means that if I create a pull request, once it is accepted, it will get merged into the
master branch, which is exactly what I want. However, I do need to click the âcompare: masterâ drop-down to tell GitHub what branch I want to create a pull request for, as you can see in FigureÂ 4-25. The âcompare:â branch is the one that Iâd like people to consider merging into
Once Iâve selected a branch, the process is just the same as it was earlier in this chapter when creating a pull request from a fork. I click the green âCreate pull requestâ button, enter a title and description to explain the reason for the pull request, and then click the âCreate pull requestâ button. This creates the pull request shown in FigureÂ 4-26.
Collaborating on Pull Requests
Pull requests are designed to start a conversation about a proposed changeâusually either a new feature or a bug fix. Originally, pull requests were created only when coding was completed to ask someone to incorporate a completed set of changes, but these days pull requests are used in a couple of different ways.
If you have a change that youâre confident about, you can still create a new branch, make all your changes, and wait to create a pull request until youâre done with the work. In such a case, the purpose of the pull request is just as a double-check to make sure that the rest of your team agrees with the changes you made before the changes get merged into
master and pushed to production.
However, there is another way to use pull requests. In many companies, employees will often create pull requests for features that theyâd like to discuss. So, if you have an idea for a change but arenât sure whether itâs a good idea, consider creating a branch and making the simplest possible start on the workâmaybe just a small text file describing it. Once you have a commit on the branch, you can then create a pull request to kick off a discussion about the idea.
Involving People with Pull Requests
If youâve created a pull request and would like feedback from specific people on a team, @mention them. To do this, within the pull request itself or in a comment on the pull request, type @ and then type in the GitHub username. If the person is the owner or a collaborator on the repository, the username will autocomplete as you start to type. You can also begin typing the userâs displayed name (which can be set in your public profile).
If you wanted to get feedback from me on some work youâd been doing, you might create a comment like âhey @brntbeer, mind looking at this PR and letting me know what you think?â The formality of the language will depend on the people youâre working with, but pull request comments are often written in a fairly informal style.
Reviewing Pull Requests
If you want to see what people are working on within a repository, go to the home page and click the âPull requestsâ tab at the top, and youâll see a list of all of the currently open pull requests.
On most projects there should be only a few pull requests open at any one time. A good rule of thumb for a private repository is that you shouldnât have more than a few open pull requests per developer. Generally, the fewer pull requests you have open, the better, as it is more valuable to keep the team focused on finishing up existing features than on starting new ones. Also, pull requests should be for small, iterative changes, to make them easier to review. The more changes that go into a branch, the longer it will live and the more difficult the changes will be to review properly. These âlong-livedâ branches arenât always avoidable, but you should be on the lookout for them.
The number of open pull requests on open source projects will typically be much larger, as anyone can create a pull request, and sometimes it takes a while for the core project team to review, accept, and/or close them.
When you find a pull request that you want to review, click it to view the pull request detail page.
Commenting on Pull Requests
A really important part of working with a development team is to take the time to review all of the pull requests that you might care about. Nothing is more disheartening than to work on a feature for a couple of days, create a pull request, and then get no feedback at all. Also remember that by default anyone can merge their own pull request into
master so long as they have write permission, so make sure to take the time to review peopleâs work so they arenât tempted to merge it in without at least one or two people having a look at it. Or, if youâd like this not to be the case, you can use protected branches to require certain approval workflows. Weâll cover some of these options in ChapterÂ 7.
Whenever you get an email or a web notification that youâve been @mentioned in a pull request, make sure to take the time to check it out as soon as you can and provide some useful feedback. Sometimes useful feedback may even be to let the person know youâll give it a good review soon. Even if youâre not named personally, taking a little bit of time out of your day to make sure that you review any outstanding pull requests and provide your thoughts to ensure everyone is on the same page with where the project is going is a good idea.
Commenting on pull requests is pretty simple. Skim down the pull request page, go to the comment box, type in your feedback, and click the Comment button.
Adding Color to Comments
Especially for a team that doesnât work in the same office all of the time, commenting on pull requests is often one of the more frequent ways that team gets to interact. Because of that, itâs often a good idea to add a little bit of fun to the interactions.
GitHub has built-in support for emoji. Emoji are small images that are often used for displaying a mood or emotion graphically. If you look at FigureÂ 4-27, youâll see that this comment has the :+1: (Iâm in support of this feature) emoji and the :ship: (letâs merge this in and âshipâ it) emoji.
Another way to add some more color to your comments on GitHub is by using animated GIFs. While emoji are subtle, most animated GIFs are much larger and more strikingâtheyâre often a great way to really lighten the mood or show strong support (or disapproval) for a change or a comment. To add an animated GIF (or any other image) to a pull request, just drag and drop it into the comment box and itâll get uploaded automatically.
Contributing to Pull Requests
Sometimes youâll want to make a change directly to a pull request. Perhaps someone has added a new page and youâd like to fix up the marketing copy, the legal disclaimer, or even the CSS to make it display better in your favorite browser. Itâs easy to make a change to someone elseâs pull request.
The process is the same as for editing a file, which we covered in the previous chapter. The only difference is that you must be on the correct branch. In this case Iâm looking at the
update_readme pull request for adding some content to the README.md file, as you can see in FigureÂ 4-28.
If I decided that it would be great if the file contained a brief description, rather than just commenting that the README was missing a contributors guide, I could add one.
To make the change, all I need to do is go to the repository home page and select the
update_readme branch from the drop-down list of branches. I can then click the file and click the edit icon, and Iâll get the edit screen, as you can see in FigureÂ 4-29.
I can then make my changes, scroll down the page, and enter some kind of commit message, as shown in FigureÂ 4-30.
Now if I go back to the pull request page, you can see in FigureÂ 4-31 that my commit has been added to the pull request. Anyone who is watching the pull request will get a notification that it has been updated so they can review my change and provide their feedback.
Testing a Pull Request
If you have the appropriate permissions, before you approve a pull request that includes substantive code changes that you canât just review visually, youâre going to want to download a copy of the repository (clone the repo). Then check out the branch that the pull request relates to, run the automated tests to make sure theyâre all passing, and then run the code and maybe do a little bit of manual testing just to make sure it seems solid. Weâll cover cloning repositories in ChapterÂ 8.
If youâre not a developer, you could leave this to your development team, but you do want to make sure that at least one or two people are downloading the code, running the test suite, and maybe doing a little manual testing before approving a pull request. Alternatively, an easier and best practice option is to set up automated testing that will run for you and report its status back to the pull request. This, as well as required reviews, can be configured inside of the protected branches settings of a repository, which will be talked about in ChapterÂ 7.
Merging a Pull Request
When youâre ready to merge a pull request, just click the large green âMerge pull requestâ button, as shown in FigureÂ 4-32.
When you do so, GitHub will ask for a commit message (the default will be the title of the pull request and an indication that this commit came in from a pull request merge), as shown in FigureÂ 4-33. Once youâve entered that, just click the âConfirm mergeâ button and the pull request will get merged and closed, as described earlier in this chapter.
You should have some kind of policy for closing pull requests. Many teams will require one or two people other than the primary author of the pull request to provide a :+1: before a pull request is merged. Have some kind of process, but keep it as lightweight as needed. Remember, you can always revert a merge, so if the code youâre working on does not have the possibility of endangering anyoneâs life, itâs generally better to âmove fast and (occasionally) break thingsâ than have a list of 27 people who need to approve every single pull request before it can be merged. However, as mentioned a few times already, if there are strict requirements they can be added in the protected branches and required statuses.
Who Should Merge a Pull Request?
One question that often comes up is whether a pull request should be merged by the person who created the pull request or by someone else.Â I generally recommend that pull requests be merged by the person who created them. Hereâs why.
Many companies have the rule that âthe person who created a pull request canât merge it.â The reason for this is to make sure that someone doesnât just create a pull request and merge it in without getting any feedback. The idea is good, but I donât think the recommendation is ideal.
Most of the time, the person who created the pull request is the person who knows the most about it. As such, I always want to have that person available when her work is merged in just in case it breaks something unexpected. One of the easiest ways of making sure that sheâs around is to ask her to do the merge. So Iâd recommend asking people to merge in their own pull requests, but making it clear that they shouldnât do so until theyâve got at least a couple of :+1:s from the rest of the team, or any other required workflows and statuses have happened.
Pull Request Notifications
If you create a pull request, comment on one, commit to one, or are @mentioned in one, by default youâll be subscribed to the pull request. This means that whenever anyone comments on, commits to, merges, or closes the pull request, youâll be sent a notification. You can see on the right side of FigureÂ 4-34 that I am currently subscribed to this pull request.
If youâre no longer interested in a pull request that youâve been subscribed to, just click the Unsubscribe button and youâll stop receiving notifications. You will get re-subscribed automatically if anyone @mentions you again in the comments. If youâre not subscribed to a pull request that youâd like to keep an eye on, just click the Subscribe button, as shown on the right in FigureÂ 4-35, and you will start getting notifications of any activity on that pull request.
Best Practices for Pull Requests
- Create pull requests for everything
- Anytime you want to fix a bug or add a new feature, make sure to do it on a branch and then create a pull request to get input before merging your work into
- Make the titles descriptive
- Other team members will be looking at the pull requests to get a sense of whatâs going on. The title should give them a good idea of what youâre working on.
- Take the time to comment
- Do this even if youâre not @mentioned. Itâll give you a good sense of whatâs going on with the project and will improve the overall quality of the work.
- @mention key people
- If you want feedback from marketing, legal, and the operations team, @mention the necessary users to ensure they see the pull request and make it more likely you get feedback.
- Run the tests
- Make sure that at least one developer downloads the latest changes from a pull request, checks out the appropriate branch, and runs your automated tests. It isnât enough just to look at the code visually for nontrivial changes.
- Have a clear policy for approving pull requests
- Most companies require that one or two people other than the primary author of the pull request review and provide a :+1: before the pull request is merged in.
Up to this point, youâve had an overview of the repository, working by yourself, and working with others. Most of the actual work on GitHub is conducted around pull requests, but what about when you just want to discuss an idea before it becomes work, or if you notice a bug in someoneâs software and you want to talk about it? Thatâs where GitHub issues come in. If pull requests are where you discuss and collaborate around code, GitHub issues are for discussing ideas and planning before a pull request is created. Continue on to the next chapter to find out more!