Getting started with Git - Part 4 - Forking & Making Pull Requests (PR)

Other posts in this series:  Getting started with Git

Let's learn about forking repositories and making pull requests. When multiple developers work on a repository, it is considered a best practice to disallow pushing directly to the master branch. Instead, the commits are made in a different branch and pushed to the remote. Then, a Pull request is opened on the remote.

Pull Requests (PR)

Pull requests are a method to notify collaborators that you've pushed a commit to a remote branch. When a branch in the Github remote is ahead or behind another branch, GitHub offers to open a pull request. Once a PR is opened, the collaborators can review the changes, request edits and if satisfied, allow the merge into the target branch.

This has the added advantage of allowing collaborators to review the code before it is merged into master. Often, organisations follow a strict code review policy, mandating that at least one developer review the code before it is pushed to master.

Our first PR

Open up the repository page on Github. We need to add a LICENCE.txt in the myapp repository. Create a branch on Github, call it hotfix-license. Click on the Create new file. Github allows editing of text files in the Web UI itself. We will commit this file to the hotfix-license branch.

After the commit, Github will notify us that we've pushed to a branch and ask if we'd like to open a Pull request.

Click on the Compare and pull request button.

Create a PR after reviewing the changes. This will land us straight to the Pull Requests tab of our repository. Here, we can review the changes, make additional commits and comment on the PR.

Click on the Merge Pull request button. Remember squashing from part 3? Github also offers an option to Squash and Merge.

You can check the commit in the Commits section on the repository page.

Well done! The licence has been added, best practices upheld and the world has one more open source repository. But, there's one thing we have yet to consider.

You can't push to a remote from a clone, unless you have the access rights.

Fork and Pull Model

Think of an open source project you are maintaining where everyone will be permitted to share/modify your code. You wouldn't want them to modify your Github repository without reviewing the changes yourself. Right?

Hosting providers like Github and Gitlab offer an option just for that, by allowing you to "fork" a repository. A fork is a copy of a repository, which allows a user to work on someone else's code without being able to modify the original. After forking a repository, the owner of the fork has the same privileges in the fork as the owner of the original repo has on the original repo.

Easier version: You are free to do whatever you want with the code, provided you stay within the bounds of the LICENSE provided with the code.

To fork the myapp repository, go to the repository page on Github and fork it. The fork button is on the right of the repository name.

To demonstrate some concepts, I asked a bunch of my friends to fork our repository and play around. Let's see what their forked repositories look like.

Seems like Rahul has made a new commit in his fork.

Pull requests across forks

When the owner of a fork makes a commit, they might also want the same commit in the original (called, "upstream") repository. Pull requests can also be made from a branch in a fork to a branch in the upstream repo.

When a branch in the Github remote is ahead or behind another branch, GitHub offers to open a pull request. Note the Pull request button below the green Clone or download button.

In the Pull requests tab on the repository page, you can see the pull requests against a repository.

We have an open pull request. Let's examine it. Let's check the Files Changed section to examine the changes made. You can examine the PR here. Everything looks good, let's merge the changes. The Merge pull request button is on the Conversations tab. You can now see that the status of the PR has been changed to "Merged".

Now will be a very good time to fork the repository. Also, clone your fork locally using SmartGit.

Merge Conflicts

Merge conflicts are very common (and very unwelcome). A merge conflict can hinder your workflow. To learn more about them, let's deliberately create a conflict and attempt to resolve it. Open the cloned repository in SmartGit. Add a branch, call this branch dev.

Open handler.js in a text editor and add some comments to make the code more understandable.

// import the required libraries
const url = require('url');
const moment = require('moment');

// define the handler function
let handler = (req, res) => {

  // parse the url string and extract the query parameters
  let queryData = url.parse(req.url, true).query;
  
  // set response code
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');

  let greetString = "";
  if (queryData.name) {
    greetString = "Hello user!\n";
  } else {
    greetString = "Hello World!\n";
  }

  let day = moment().format('dddd');
  if (day === "Friday") {
    greetString += "Thank God! It is FRIDAY!"
  } else {
    greetString += ("It's " + day);
  }
  res.end(greetString);
};

// export the handler function
module.exports = handler;

Commit this file in the dev branch.

Now checkout master and modify it to console.log every request. Add this line to the handler function.

console.log(req.headers)

Commit this file in master.

Try to Merge from dev into master. Right-click on dev and select Merge. Choose the Merge to Working Tree option from the dialog box.

You will find that the Merge operation has been unsuccessful. There are conflicting changes to the handler.js in the develop and master branches. In a merge conflict Git fails to decide which changes to put into the result and which ones to ignore. Merge conflicts generally happen when two developers modify the same lines in a file.

We can solve this by reviewing the changes ourselves. Right click on the handler.js file in the Files section and select Conflict Solver. Edit the Working Tree section, checking the red areas.

Click on the Save button on the toolbar and commit this file from the Log view.

What next?

Having fun yet? Go ahead and fork any open source project you want. Keep tinkering with your fork till you break something, and then learn how to fix it. Stay tuned and keep committing. Contact us at contact@attosol.com for your software and consultancy requirements.

© 2023, Attosol Private Ltd. All Rights Reserved.