/ by

How to handle Git workflow complexities?

Introduction

In the ever-evolving world of software development, it is crucial to have a reliable and efficient workflow to manage codebases. Git, the widely adopted version control system, offers a plethora of practices to streamline collaboration and maintain code quality. But with so many branching strategies and workflow options to choose from, how do you determine which one is the best fit for your project? In today’s blog post, we will delve into the realm of Git flow, dissecting the top-performing workflows for code-based developments, and offering expert insights to help you make an informed decision. So, strap in and get ready to revolutionize your team’s coding experience by adopting the most effective Git flow for your unique needs.

Branching

Main

A public branch that represents the official release history. Developers are not directly committing changes to the main branch. All releases are tagged with a version number (i.e. v1.0.0) for convenience. Contains an abridged version of the project.

Develop

A public branch that represents the official project history. Developers are not directly committing changes to the develop branch. This branch serves as an integration branch for features. Contains the complete history of the project.

Feature Branches

The developer is creating a new feature branch every time he starts working on a new feature. These branches should have descriptive names like “issue-#1015” (referring to a Jira ticket for example) or “forgotten-password-functionality”. The idea is to give the branch a specific purpose. Features should never interact directly with main.

Feature branches should be pushed to the central repository (instead of just working locally on your machine) for backup & collaboration. Since main is the source-of-truth branch, having multiple feature branches on the central repository (remote) does not pose any threat.

Feature branches are, in general, created off to the latest develop branch. When you’re done with the development work on the feature, the next step is to merge the Feature branch into develop.

Release Branches

Once develop has acquired features for a release, a release branch should be forked off of develop. Once the branch is created, the release cycle has begun. This means no new features are to be added after this point. An exception is made for bug fixes, documentation, and other release-oriented tasks.

Once the release is approved and ready to go – it is merged into the main branch. It is then tagged with a version number. It also should be merged back into develop (it may have progressed since the release was initiated).

A dedicated branch to prepare releases makes it possible for one team to polish the current release while another team continues working on features for the next release.

Like feature branches, release branches are based on the develop branch.

Once the release is ready to ship, it will get merged into main and develop, then the release branch will be deleted. It’s important to merge back into develop because critical updates may have been added to the release branch and they need to be accessible to new features.

Hotfix Branches

Hotfix branches are used to patch production releases as fast as possible. They are a lot like release branches and feature branches, except they’re based on the main instead of develop.

This is the only branch to be forked directly off of main. As soon as the fix is done, the branch should be merged into both main and develop (or the current release). Main should, again, be tagged with an updated version number.

Hotfix branches are useful to address bugs and issues without waiting for the next release cycle or disrupting the already established workflow.

Getting Started

The first step would be to create a complementing branch to the main one. That should be the develop branch. This could be done by a developer by simply creating a new branch off of the main one.

Once this step is done all the developers should clone the central repository and create a tracking branch for develop.

Proceed with the workflow creating branches as per the needs of the project as described in the previous section.

Overall flow

As per Atlassian recommendations:

  1. A develop branch is created from main
  2. A release branch is created from develop
  3. Feature branches are created from develop
  4. When a feature is complete it is merged into the develop branch
  5. When the release branch is done it is merged into develop and main
  6. If an issue in main is detected a hot-fix branch is created from main
  7. Once the hot-fix is complete it is merged to both develop and main

Branch Naming Convention

Ideally, the feature, release, and hot-fix branches should be named after a Jira or any other issue tracking product’s tickets. For example, a feature called “Add forgotten password functionality” with Jira number “WEB-5823” could result in the creation of a branch named either feature/forgotten-password or feature/WEB-5823.

  • master / main
  • develop
  • feature/<name-of-feature>
  • release/<release-name>
  • hotfix/<name-of-hotfix>

Practical Walkthrough

We are starting a new project at Ulpia Tech and we have decided to leverage the approved git workflow in order to collaborate and manage releases with ease. Let’s meet the team:

  • John, Software Engineer
  • Marry, Software Engineer
  • Peter, QA Engineer
  • Angelica, Release Engineer
  • Liam, Lead Software Engineer
  • Isabella, she’s from the business

Let’s get started! Angelica has set up the repository for the team as follows:

  • main branch
  • develop branch forked off of main

On the first day of work, the development team is assigned two tasks on the project. Each task has a respective Jira ticket for it – Isabella has been involved in their creation:

  • WEB-4001: Create login page | assignee: John
  • WEB-4002: Create register page | assignee: Marry

Both John and Marry pick up their tasks and to do so create separate feature branches. The repository now looks like this:

  • main branch
  • develop branch
  • feature/WEB-4001 branch forked off develop
  • feature/WEB-4002 branch forked off develop

Note that all branch HEADs point to the same commit

John and Marry are now committing their changes to the respective branch they are working on. While John continues the work on his task Marry decides she’s done with the implementation of hers. The feature she developed is then reviewed and approved by Liam, all automated tests she has written along with the feature have passed, Peter, the QA engineer has switched to the feature and tested it himself, and Isabella has confirmed that the feature meets the expectations. This means the feature is ready to be pushed to the develop branch. The git repository is currently looking like this:

Each of the feature branches now contains three commits

She had gone to eat lunch during her workday so she decided to commit her changes prematurely. In the end, she has three commits for her feature, but she would like only one – this is why she decides to squash them first.

She is now ready to finally promote her changes to the develop branch where regression tests will run. Angelica has instructed her to keep the history on develop as clean as possible so Marry is merging her feature by fast-forwarding the develop branch. This results in a clean linear history of the repository. She is then deleting her feature branch. The git repository now looks like this:

In the meantime, few new tasks were created (with Jira numbers as seen below):

  • WEB-4003: Add forgotten password feature | assignee: John
  • WEB-4004: Add right to be forgotten | assignee: John, Marry
  • WEB-4005: Creating monitoring dashboard | assignee: John, Marry
  • WEB-4006: Add terms of use page | assignee: Marry

Marry has now begun to work on her next feature with the highest priority which is “WEB-4006” – to do that she created a new feature branch forked off of the latest state of develop. In the meantime, John has further developed his feature by adding more commits to feature/WEB-4001. The repository now looks like this:

John’s feature has passed the approval process and he is looking forward to promoting his changes in the develop branch now. He will again squash the commits into one to maintain cleaner history. However, he noticed there is an update that happened in develop after the time of his fork of the branch. He was instructed to resolve this first in his feature branch before proceeding.

On his first step (tidying the history) the repository looked like this:

To resolve the issue with his branch being created off of outdated commit, he has then rebased develop into his own. The repository then looked like this:

Finally, John is in a position to safely merge his branch into develop by a fast-forward, then deleting the feature/WEB-4001 branch. In the end, the clean history of the repository looks like this:

By using techniques already discussed, the developer team has merged the feature/WEB-4006 to the develop branch. The repository’s state just before the creation of the release branch could be seen below:

The time for the release has come, but there is the first major issue the team is facing: the business has asked the team to not release the register page yet – in order to allow only whitelisted users to go into the system at first. This means the release should only contain the login page and the terms of use page features. To do this the team is creating the release branch and then dropping the register page feature. Let’s see how they did it:

  1. They created a new branch called release/1.0.0 by forking off the develop branch
  2. Dropped the unwanted feature from the release branchDue to the dropped commit, it now looks as if the release was branched off of the main, but don’t worry that’s not the case
  3. The changes are introduced directly to the release branch, but these fall under the “documentation” category, such changes are allowed to be made directly in the release branches so the team doesn’t break a sweat over it
  4. The interested parties and the QA team are all now looking at the release/1.0.0 branch. A small issue was found in the login page feature. The team now has to decide whether they want to also drop that feature from the release or implement a bugfix directly in the release branch – this (pushing a bugfix directly to the release branch) is also allowed and not breaking the agreed workflow. The team has chosen option number 2.
  5. Finally, all tests pass and requirements and expectations are met. The release branch is getting squashed and merged both at develop and main (after that the release branch could be safely deleted). The final result of the first successful release for the team is looking like this:
  6. The team is celebrating its success. However, it turns out that there was a critical issue on the login page that cannot wait to be fixed on the next release. The team has been advised to make use of a hotfix branch. They are creating one directly off of the main branch and implementing the fix there:
  7. Once the hotfix is implemented, it is pushed back to the main branch. It is also being applied to the develop branch. The new commit on the main branch is getting tagged with the hotfix version which is now v1.0.1.
  8. In the end, the hotfix branch is no longer needed, and the team is finally happy to close its first release.

Appendix

GitFlow Git Wrapper

Git-flow is a wrapper around Git. The git flow init command is an extension of the default git init command and doesn’t change anything in your repository other than creating branches for you. All the commands exposed by the wrapper could be found in its documentation.

Contact us

Get in touch and ask us anything. We're happy to answer every single one of your questions.

  • 6A Maria Luiza Blvd, Plovdiv
    4000, Bulgaria
  • Ulpia Tech LinkedIn Ulpia Tech Twitter


    To top