Branching in Git, Done the Right Way

Just using a version control system like Git, isn’t enough, if you are not using its best feature, Branches.

If you aren’t using a version control system in your project then STOP whatever you are doing right now, and START using one.

But first, the question is!!

Answer 🥁🥁drum roll please🥁🥁.. ALWAYS!!
No matter the team size 0,1,2,3,4,5,6,7…100………..9999999999, No matter whatever excuses you have, you have to use branches.

The type Git workflow detailed here is called GitFlow Workflow. GitFlow Workflow was published and made popular by Mr. Vincent Driessen at nvie.

We’ll start with the different types of branches that we need to have

  1. Master/Main
  2. Development
  3. Feature
  4. Release
  5. Bugfix
  6. Hotfix

It’s Story Time!!

Let’s take a small team of three developers, Goku, Vegeta, and Gohan working on a project.

  1. Let’s say Goku is the Lead developer, He sets up the repository.
  • He creates a new project folder and a readme.md file inside the project folder, on his local machine and creates a new empty repository on GitHub, GitLab, or Bitbucket, etc.
  • Initializes a git repository in the project folder
$ git init
$ git remote add origin <repository-remote-url>
$ git add .
$ git commit -m "Initial commit"
$ git push -u origin master

This creates a master branch in the repository

Master branch, As the name says it’s the Master of all the branches. Think of the Master branch as an ocean, and the other branches as rivers, eventually all the other branches end up getting merged with the master, similar to how rivers end up flowing into the ocean. The Master branch should always contain production-ready, stable code. No Commits should be made directly to the Master branch from here on. Only reviewed, approved and stable code from the Release branch should be allowed to be merged to the Master branch. Generally, it’s a good practice to only allow the Lead developers or senior developers to approve the merge request to the Master branch.

  • Creates a new development branch from the master branch
$ git checkout -b development origin/master
$ git push -u origin development

Development branch is a branch where generally any new feature development gets integrated. Is is also called as integration branch. It should always be in a state where it’s ready for the next/upcoming release. The Master and Development branches contain the complete history of the project. The Development branch exists parallel to the Master branch.

2. Now the other developers Vegeta and Gohan clone the project repository locally in their respective systems.

$ git git clone <repository-remote-url>
$ git remote add origin <repository-remote-url>

3. Vegeta and Gohan are assigned to develop FeatureA and FeatureB.

As Vegeta and Gohan are working independently on both the features, it is not ideal for them to work on the development branch. Hence they both create two new branches called feature branches.

  • Vegeta creates a new branch called FeatureA branch from the development branch and publishes the branch on the remote repository. He starts developing and performing commits to the FeatureA branch.
$ git checkout -b feature/FeatureA origin/development
$ git push -u origin feature/featureA

Feature branch is a branch created when a new feature has to be developed. It is branched off from the Development branch. The Development branch is the parent of the Feature branch. When the feature development is completed, it is merged back into the Development branch.

  • Vegeta completes the development of the FeatureA and wants to merge the FeatureA branch with the development branch.
  • He creates a pull request to merge FeatureA branch with the development branch.

Pull Request notifies the team members. The members of the team can review the code and suggest changes if required. Generally, the Lead developer approves the merge request after the code is reviewed.

  • Gohan follows the same process as Vegeta and after completing the development he creates a pull request for FeatureB.
  • Goku reviews and approves the merge request and merges the feature branches FeatureA and FeatureB with the development branch.

The merge can be performed on the GUI or by following commands

$ git checkout development
$ git merge feature/FeatureA
$ git push origin development
  • After the merge, the local and remote versions of the Feature branches FeatureA and FeatureB are deleted.
$ git branch -d feature/FeatureA  #deleting local branch
$ git push origin --delete feature/FeatureA #deleting remote branch

4. After the completion of the features by Vegeta and Gohan, the application is ready for release.

  • Goku creates a new Release branch called ReleaseV1 from the development branch and publishes the branch on the remote repository.
$ git checkout -b release/ReleaseV1 origin/development
$ git push -u origin release/ReleaseV1

Release Branch, After the development of features that are planned for release are completed, the application is ready for a release cycle. The Release branch is created from the latest Development branch. After the Release branch is created no new features should be added to the respective Release branch. Having a separate Release branch, helps the team perform QA and Testing and fix the bugs before the application is being released, and the team can continue with developing new features on the Development and Feature branchs.

5. During the QA and Testing process, some bugs arise in FeatureB which was developed by Gohan.

  • Gohan creates a new BugFix branch called BugfixV1 from the Release branch ReleaseV1 and publishes the branch on the remote repository.
$ git checkout -b bugfix/BugfixV1 origin/release/ReleaseV1
$ git push -u origin bugfix/BugfixV1

Bugfix branch, I guess by now you would have understood what’s a BugFix branch. Bugfix branch is created to have bugs fixed and then be merged back. Bugfix branches can be branched off from Release, Development, and Feature branches. If the Bugfix branch is created from the Development or Feature branches, it has to be merged back to them respectively. If the Bugfix branch is created from a Release branch, then it has to be merged back into the Release branch and also the Development branch. After the merges, the Bugfix branches are deleted.

  • After the bugs are fixed the BugfixV1 branch is merged into the ReleaseV1 branch and also to the development branch.
  • The same process of the pull request is performed during the merging of the Feature branches with developement branch are followed here. Pull request is created by Gohan, code is reviewed, approved, and merged into the ReleaseV1 branch and development branch by Goku.

The merge can be performed on the GUI or by following commands

$ git checkout release/ReleaseV1
$ git merge bugfix/BugfixV1
$ git push origin release/ReleaseV1
  • After the merging of the BugfixV1 branch with the ReleaseV1 branch and the development branch, the local and remote versions of the BugfixV1 branch are deleted.
$ git branch -d bugfix/BugfixV1  #deleting local branch
$ git push origin --delete bugfix/BugfixV1 #deleting remote branch

6. The bugs in the ReleaseV1 branch are fixed and the application is ready for production deployment.

  • After the process of QA, testing, code reviews, etc. the ReleaseV1 branch is merged with the master branch by Goku.

The merge can be performed on the GUI or by following commands

$ git checkout master
$ git merge release/ReleaseV1
$ git push origin master
  • After the merging of the ReleaseV1 branch with the master branch, the local and remote versions of the ReleaseV1 branch are deleted.
$ git branch -d release/ReleaseV1 #deleting local branch
$ git push origin --delete release/ReleaseV1 #deleting remote branch

7. Some critical bugs arise in the production application and are required to be fixed immediately.

  • Goku creates a Hotfix branch HotfixV1 from the master branch and publishes the branch on the remote repository.
$ git checkout -b hotfix/HotfixV1 origin/master
$ git push -u origin hotfix/HotfixV1

Hotfix branch, as the name suggests is created when hot/immediate fixes are required for the production application. This is the only branch that should be created from the master branch. It is merged back into the master branch and also into the Development branch. After merging, the Hotfix branches are deleted.

  • The bugs are fixed and the HotfixV1 branch is merged into master and development branches.

The merge can be performed on the GUI or by following commands

$ git checkout master
$ git merge hotfix/HotfixV1
$ git push origin master
  • After the merging of the HotfixV1 branch with the master and development branch, the local and remote versions of the HotfixV1 branch are deleted.
$ git branch -d hotfix/HotfixV1  #deleting local branch
$ git push origin --delete hotfix/HotfixV1 #deleting remote branch

Done!! The flow is complete.

Don’t you think this feels too smooth like a fairy tale, creating branches and merging them? If you have thought that, then you have thought right.

Welcome to something called Merge Conflicts. Yes, you heard it right “Conflicts”. Sometimes it also causes conflicts within the team😈.

8. Vegeta while working on the FeatureA branch modifies a function to take in two arguments, argA and argB def myfunction(argA, argB): in a file called app.py, Gohan when working on the FeatureB branch also modifies the same function to take one argument argC def myfunction(argC): in app.py file.

  • Vegeta makes the pull request for the FeatureA branch to be merged with the development branch first and his branch gets merged without any issues.
  • Gohan creates a pull request for the FeatureB branch to be merged with the development branch and during merging he is hit with a Merge Conflict.

Why? you ask!! It's because Vegeta and Gohan have edited the same line in a file in two different branches. When Vegeta and Gohan had created two branches from development the function in the app.py file was def myfunction(): , Gohan wasn’t aware of the changes made by Vegeta.

  • Gohan checks the file which has conflicts and tries to resolve them. He consults with Vegeta regarding this issue and comes to a conclusion to modify the function to def myfunction(argA, argB, argC): and makes the merge commit.

There are many ways to resolve a Merge Conflict, I have just mentioned one scenario here. There might be cases when both the changes in the branches are kept, one change is removed and the other one is kept and vice versa and so on.

The main things required during resolving Merge Conflicts are proper communication and patience between the stakeholders/team members involved.

In this article, I wanted to give an overview of Branching in Git, by taking Gitflow Workflow. I hope by reading this article, you will get, at the least a basic idea on Branching in Git

There are different types of Git workflows, GitFlow (the one we have talked about in this article), GitHub Flow, Gitlab Flow, Centralized, Feature Branch, Forking Workflows, etc. Different workflows can be adapted based on the team sizes, deployment strategies and the type of project, etc. You can also create your own custom workflow based on your requirements.

To Summarise:

  • Development branch is created from the Master branch
  • Feature branchs are created from the Development branch and are merged back into the Development branch.
  • Release branchs are created from the Development branch and are merged into the Master branch.
  • Bugfix branches can be created from Development, Feature branches and are merged back into the respective branches from which they are created. If Bugfix branches are created from the Release branches, the have be merged back into the respective Release branches and also into the Development branch.
  • Hotfix branches are created from the Master branch and are merged back into the Master branch and also into Development Branch.

Cast in order of appearance: Goku as the Lead Software Developer, Vegeta and Gohan as Software Developers.

Thank you!!