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

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. create new branch on remote 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. add licence.txt

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. compare and pull request button

Click on the Compare and pull request button. create pull request

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. pull requests tab

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

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

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. Original repository on Github

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

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

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. pull request button on rahul's fork

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

We have an open pull request. Let's examine it. alt Let's check the Files Changed section to examine the changes made. You can examine the PR here. alt 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". alt

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. new branch added

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. commit handler.js in dev

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

console.log(req.headers)

handler.js in vscode Commit this file in master. commit 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. merge-options

You will find that the Merge operation has been unsuccessful. merge-output 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. conflict-solver-initial Edit the Working Tree section, checking the red areas. conflict-solver-final

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

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 for upcoming articles. You may contact us for your software and consultancy requirements.

© 2024, Attosol Private Ltd. All Rights Reserved.