Getting started with Git - Part 3 - Branching & Merging

Other posts in this series:  Getting started with Git

Let's now learn about how Git is used in the real world.

Controlling Version Mayhem

You must have noticed how most famous projects give you a way to hook into the project's different versions like nightly, weekly or monthly builds, alpha & beta channel, and a stable release with a semantic versioning. It helps the developers in achieving feedback on new features before they introduce it in the final builds. It also helps in faster development without breaking the software or user experience. End users have different risk appetite when it comes to consuming a software. Some prefer the latest builds even at the cost of unexpected bugs and weird issues (in the daily builds) at the cost of stability, while others detest crashes and would rather prefer using a stable version. Git can help you achieve this with ease. Your team can:

  • work on experimental features that are kept separate from the working code base.
  • fix bugs in a specific version and release hotfixes.
  • do regular ongoing development swiftly in an agile fashion.

Branching to the rescue

Branching in Git helps us maintain separate lines of development in the same repository. Think of a branch as a separate workspace. The main branch, generally called master is like the trunk of a tree. All branches emerge from some point (in the commit history) on the trunk (or master) or another branch.

To follow along, open SmartGit and clone the repository for our tutorial. You will also note that, it's hosted on GitLab, which is another repository hosting provider. Open the Commit Log view of the repository (right click on repository name and select Log). The Log view gives a better bird's eye overview of the repository.

Click on the Branch button on the Menu bar and select Add Branch. We will call the branch dev. Click on the Add Branch & Checkout button when you're done. A checkout changes the "workspace" or the current branch. Note that the Branches section in the bottom-right shows that we are now in the dev branch.

Modify the handler.js file to return a JSON response.

const url = require('url');
const moment = require('moment');

let handler = (req, res) => {  let queryData = url.parse(req.url, true).query;
  res.statusCode = 200;
  res.setHeader('Content-Type', 'application/json');

  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(JSON.stringify({message: greetString}));
};

module.exports = handler;

Commit this file, note that the master branch is unchanged and the dev branch moves ahead of the master branch.

More branches

We plan on adding a new feature to the app. Creating separate branches for each feature being worked on is a good practice. Add a new branch and call it feature-painters-week. When we add a branch, it comes out of the current checked-out commit (which is the last commit unless we manually checkout a different commit). Our feature branch will "emerge" from the dev branch. Now make a bunch of commits in this branch.

Add artists data

Add the new file artists.js, which will hold the data for the API. Create the file and commit it.

const map = new Map()
map.set("Monday", {
  name: 'Claude Monet',
  nationality: 'French',
  bio: 'https://www.theartstory.org/artist-monet-claude.htm'
})
map.set("Tuesday", {
  name: 'Rembrandt',
  nationality: 'Dutch',
  bio: 'https://www.britannica.com/biography/Rembrandt-van-Rijn'})
map.set("Wednesday", {
  name: 'Vincent van Gogh',
  nationality: 'Dutch',
  bio: 'https://www.theartstory.org/artist-van-gogh-vincent.htm'
})map.set("Thursday", {
  name: 'Michelangelo',
  nationality: 'Italian',
  bio: 'https://www.britannica.com/biography/Michelangelo'
})
map.set("Friday", {
  name: 'Andy Warhol',
  nationality: 'United States',
  bio: 'https://www.theartstory.org/artist-warhol-andy.htm'
})
map.set("Saturday", {
  name: 'Pablo Picasso',
  nationality: 'Spanish',
  bio: 'https://www.theartstory.org/artist-picasso-pablo-life-and-legacy.htm'
})
map.set("Sunday", {
  name: 'Leonardo da Vinci',
  nationality: 'Italian',
  bio: 'https://www.britannica.com/biography/Leonardo-da-Vinci'
})

Remove weekday from greeting

Modify the greeting and commit it.

const url = require('url');
const moment = require('moment');

const artists = require('./artists');

let handler = (req, res) => {
  let queryData = url.parse(req.url, true).query;
  res.statusCode = 200;
  res.setHeader('Content-Type', 'application/json');

  let greetString = "";
  if (queryData.name) {
    greetString = `Hello ${queryData.name}!`;
  } else {
    greetString = "Hello anonymous user!";
  }
  let day = moment().format('dddd');
  if (day === "Friday") {
//    greetString += "Thank God! It is FRIDAY!"
  } else {
//    greetString += ("It's " + day);
  }
  res.end(JSON.stringify({message: greetString}));
};

module.exports = handler;
Add export to artists.js

Append the line below to artists.js and commit.

module.exports = map;
Hook everything together

Modify the handler.js file and commit it.

const url = require('url');
const moment = require('moment');

const artists = require('./artists');

let handler = (req, res) => {
  let queryData = url.parse(req.url, true).query;
  res.statusCode = 200;
  res.setHeader('Content-Type', 'application/json');
  let greetString = "";
  if (queryData.name) {
    greetString = `Hello ${queryData.name}!`;
  } else {
    greetString = "Hello anonymous user!";
  }
  let day = moment().format('dddd');
  
  const painter = artists.get(day);

  res.end(JSON.stringify({
    message: greetString,
    day: day,  
    painter: painter
  }));
};

module.exports = handler;

The feature-painter-week branch is 4 commits ahead of the develop branch.

Try running the app, run node app.js from the terminal and open localhost:3000 in a browser.

Merging

While multiple workspaces are helpful, multiple incoherent copies of the codebase are not. Work done in a branch needs to be "brought back" to the trunk at some point. We created a feature branch to isolate the development of that feature. Now that the feature is complete, it's time to merge it back into dev.

Merge feature branch into dev

To merge feature-painter-week branch into dev,

Checkout the dev branch by double-clicking on dev from the Branches section in bottom-right. Right-click on feature-painter-week in the Branches section and select Merge. There are multiple approaches to merging. For now, select the Create Merge-Commit option. This creates a separate Merge commit in dev.

The feature-painter-week branch has been merged into dev.

Change version of app

We have added a new feature to our app. In the dev branch, open the package.json file, modify the version and set it to 2.0.0. Commit this change.

Merge dev into master

Version 2.0 of our app is ready. It's time to merge dev into master and ship it !

  • Checkout the master branch.

  • Right click on dev and select the Merge option.

  • This time, click on Merge to Working Tree button. The Working Tree is in merging state and changes from the dev branch are staged.

  • Click on the Commit button from the toolbar.

  • Choose the simple commit (one parent, "squash") option and modify the commit message.

  • Click on the green Commit button. Note that there is a straight line from prep for part 3 to v2.0 painters week in the commit log. All the commits in dev branch have been "squashed" into a single commit. We can now ship/push the master branch and discard the develop and feature-painter-week branch and our commit history will contain no information on those commits. Squashing is often used to keep the commit history clean.

What next?

In the next section, we will cover forks, pull requests and merge conflicts. Stay tuned for upcoming articles and this series on Git. You will learn about various cross-platform GUIs for Git. Contact us at contact@attosol.com for your software and consultancy requirements.

© 2023, Attosol Private Ltd. All Rights Reserved.