Git Best Practices — GitFlow Branching model

Thushara Jayasinghe
8 min readApr 27, 2018

--

Image Credit : https://optimalbi.com/blog/2018/02/13/why-git/

Introduction : There are plenty of materials available to learn Git. But managing Git in a large scale project is challenging. This article will cover a real life example of effective Git usage from the initial setup to go live face.

Scenario : TechLogic (Pvt) Limited got a new project called iHRM, a HRM software solution for a client in UK. They decided to adopt scrum practices for incremental deliveries. Scrum team consists of 5 developers, 2 QA’s and a Scrum master. TechLogic was using SVN as the source control management system. But there was a request from client to use Git for this project. During Sprint grooming Rob, lead developer was allocated for initial Git setup and Login story. Lynda took the change password functionality.

  • John’s JIRA ticket id is iHRM-123
  • Lynda’s JIRA ticket id is iHRM-890

What is Git ?: Git is the widely used source control management system in world. Git was developed by the Linus, the founder of Linux in less than two weeks. Git is a distributed version control system in contrast to SVN.

SVN vs. Git

SVN:

  • One central place to store the master copy
  • You checkout the code from master copy
  • Do your changes locally
  • Push the changes to master copy

Git:

  • Users maintain their own repositories instead of a central repository
  • By convention a repository is selected as the master, but that is not built-in to Git
  • No single point of failure

The confusing point for the team is the concept of local repositories and remote repositories which is not the case for SVN

Understanding git architecture

https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control

Installing Git in Windows

https://git-scm.com/download/win

Branches: Git branches can be used to manage changes effectively and interdependently from other developers/changes. But managing branches in a real life project can be complex when multiple features are developed. It will get worse when multiple releases are done in parallel. In our example client is testing the home page and they want to test the bug fixes in agile manner (an EBF). Any new feature development should not be appear in this version until the next scrum iteration. GitFlow is a proven branching model invented by Vincent Driessen to handle such scenarios. Similar model can be found in git book as well.

The way Git keeps file is amazing. Refer below URL.

Git file storage

GitFlow: http://nvie.com/posts/a-successful-git-branching-model/

In GitFlow there are main branches and supporting branches.

GitFlow Branching Model

Main Branches

  • master
  • develop

The master branch at origin should be familiar to every Git user. Parallel to the master branch, another branch exists called develop.

We consider origin/master to be the main branch where the source code of HEAD always reflects a production-ready state.

We consider origin/develop to be the main branch where the source code of HEAD always reflects a state with the latest delivered development changes for the next release. Some would call this the “integration branch”. This is where any automatic nightly builds are built from.

When the source code in the develop branch reaches a stable point and is ready to be released, all of the changes should be merged back into master somehow and then tagged with a release number.

Supporting Branches are used for ongoing development of feature/bug fixes by developers.

  • May branch off from develop
  • Must merge back intodevelop
  • Feature branches are used to develop new features for the upcoming or a distant future release.
  • It exists as long as the feature is in development, but will eventually be merged back into develop.
  • Feature branches typically exist in developer repository only, not in origin. But it is not the case when pull requests are used for merging purposes.
  • Developers should create separate branches for their respective features.
  • Instead of basing it on master, developers should base their feature branches on develop

Git Branch Naming Convention: Defining a naming conversion is really important when multiple scrum teams are working in a single project. It should be possible to identify the change that has been done and the personal responsible for the change simply by looking at the branch name. Below is something

feature/<developer name>/<ticket-id>/<change-description>

Example :

feature/john-mac/ticket-123/login-module

Having ticket id in branch name has an additional advantage if you are using Attlasian product suit. A hyper link for your branch in Bitbucket will be created in JIRA ticket so that navigation from the ticket to the branch is possible.

Lets come back to our Sprint. Company Git repository has been successfully installed by the admin team. John started creating branching model in remote repository as per GitFlow model. He cloned the empty repository into his laptop and created his own local repository as below. Then developbranch is created locally and then pushed to remote branch. This remote develop branch will be used to keep the latest code changes the project.

git clone <URL>
git checkout -b develop
git push origin develop

Now John needs to create his own local feature branch for change password logic implementation. This feature branch should be created from the tip of the develop branch. Therefore he first need to switch into develop branch and then create the feature branch.

git checkout develop
git checkout -b feature/john/ticket-123/login-module

John continues his development in his IDE and once testable increment is completed and tested, those changes should be pushed to remote develop branch. There can be changes in develop branch pushed by other developers in the team when John tries to update the develop branch with his changes. Therefore he need to apply (merge) those changes into his feature branch before pushing changes to remote develop. If not changes in develop will be overridden.

git add .
git commit -am 'initial login method completed'
git checkout develop
git pull origin develop
git merge feature/john/ticket-123/login-module
git push origin develop

In the meantime Lynda is getting ready to start the development of change password functionality. Lynda needs to get a copy of company repository into his local laptop. It can be done using git clone command. Then he need to fetch all the branches from company repository using git fetch command. Since latest changes are present in develop branch Lynda needs to switch to develop branch and then create a new feature branch from the tip of the develop branch.

git clone 
git fetch
git checkout develop
git branch -b git checkout -b feature/lynda/ticket-890/change-password

Now Lynda can do the required code changes for change password logic. These changes are tracked by git as staging changes. Once changes are done Lynda can push these changes to remote develop. Lynda also should merge her code with latest develop branch to before pushing to remote.

git status
git add .
git commit -am 'adding change password logic'
git checkout develop
git pull origin develop
git merge feature/lynda/ticket-890/change-password
git push origin develop

Fast forward merge : When merging it is required to keep a simple history of commit messages rather than having all messages

http://stackoverflow.com/questions/2850369/why-does-git-fast-forward-merges-by-default

Rebase : https://hackernoon.com/git-merge-vs-rebase-whats-the-diff-76413c117333

https://git-scm.com/book/en/v2/Git-Branching-Rebasing

Pull Request : The recommended method is to use pull requests to update your develop branch. The direct push permission for the develop branch should be restricted. When using pull requests John should push his feature branch to company repository and create a request to merge his feature branch to develop branch using git web console. When creating John can assign reviews for code review purposes. Those reviewers can see the code diff that John has created and reject/approve the request. If code review is approved then John can merge his feature branch to develop branch.

Stashing Changes : Lynda came across a run time issue in his feature branch and she needs some help from John to fix it. But John is in the middle of his development in his own branch and these changes are still not ready commit. Git stash command is handy in such situation where John can save his uncommitted changes temporary and switch to Lynda’s branch for investigation purposes. When investigation is finish John can apply his uncommitted changes back to his branch from the temporary store.

//stash uncommitted changes
git stash
//fetch all remote branches
git fetch
//switch to Lynda's branch
git checkout feature/lynda/ticket-890/change-password
//once troubleshoot is completed
git checkout feature/john/ticket-123/login-module
git stash apply

Release Tagging: Time goes fast. We have come to the end of Sprint and client is waiting to test the iteration. In the mean time stories for the next spring are getting groomed for the development. Client release should not be affected by the planned development activities. Therefore it is required to mark a release number in Git repository. It can be done by creating a release branch.

git checkout develop
git pull origin develop
git checkout -b release-1.0.0.1
git push origin release-1.0.0.1

This tag should be checkout for EBF’s and other maintenance CR’s. https://git-scm.com/book/en/v2/Git-Basics-Tagging

Handling an EBF: A critical bug has been found in login module and it is required to fix it immediately. John needs to create a bug fix branch by using as the release-1.0.0.1 as the head.

git fetch
git checkout release-1.0.0.1
git checkout -b hotfix/john-mac/ticket-1123/fixing-password-complexity-valation
//fix the bug
//git add .
git commit -am 'Ticket-1123 invalid password complexity validation issue fixed'
git checkout release-1.0.0.1
git pull origin release-1.0.0.1
git merge --no-ff hotfix/john-mac/ticket-1123/fixing-password-complexity-valation
git push origin release-1.0.0.1

This new release should also be marked in Git.

git checkout release-1.0.0.1
git pull origin release-1.0.0.1
git checkout -b release-1.0.0.1_ebf_1
git checkout release-1.0.0.1_ebf_1

Any further hot fixes should be done in release-1.0.0.1_ebf_1 branch.

Cheery pick :The above bug identified in login module is present in develop branch as well. There for the fix should be copied to develop branch as well. There can be other fixes in release branches where those fixes should not be copied to develop branch. Only the selective commit message should be copied to develop branch. Git cherry pick is the solution. Cherry picking means choosing a commit from one branch and applying it to another branch. Let assume the commit hash of the bug fix is :9772dd546a3609b06f84b680340fb84c5463264f

git checkout develop
git pull origin develop
git cherry-pick 9772dd546a3609b06f84b680340fb84c5463264f
git push origin develop

https://stackoverflow.com/questions/9339429/what-does-cherry-picking-a-commit-with-git-mean?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

Conclusion: GitFlow branching model is an effective branch management workflow for real life projects.

--

--