Just another git flow

Shubham Najardhane
6 min readFeb 11, 2024

--

GIT, you must have come across git commands in your day-to-day life. (developers life)

git add 
git commit -m "my days work"
git push

And boom, you are done with GIT. You are a git expert.

But wait, is it as simple as that? This is just the “hello world” of GIT. As a college student, for a lone developer, it’s good to know these commands. But this might not work for a real-life projects.

Having a version control system is an absolute necessity for your project. It might vary from project to project, development strategies, QA process, and team size. Without a proper flow, it becomes very difficult to manage your code. There is no defined set of rules. I consider GIT as an essential toolbox you can use it as you want. Hey, go ahead and use the spanner as the hammer if that whats suits you better, toolbox doesn't come with the set of guidelines either.

Let’s talk about how we have set up the flow here at Zinrelo

Before we jump into the git-flow configuration, let’s get a brief idea about our team and development setup, our problems too, and how we tackle those.
Previously, we were a small team, with 5–6 developers and only one QA. Being a small development team individuals were responsible for driving the entire feature. We used to create a feature branch from develop and then test out the complete feature branch. Once done merge it back into the develop. And at the end merge the develop to release to perform sanity and then to main for the production deployment.

Bottlenecks

Soon we hit the bottlenecks with this process. As the team size grew we started struggling with GIT. We slowly started sinking into issues because of the current GIT structure.

1. Since we got multiple QAs in our team, it became difficult to spin up separate environment to test out individual features. As it was not cost-optimized strategy for us

2. Difficult to look into the past. As lots of unnecessary merge commits and multiple commits related to that feature. It became difficult to track down the code for the individual feature. No single place to find out all the commits related to a particular feature

3. With the plain merge, recently released items are getting stacked down in history. As those were committed to feature branch ages back.

Now setting up the standard flow became an absolute necessity for our project. So that developers don’t have to hustle with GIT every time they work. We decided to solve all the above problems and came up with the below structure. We have started this on a trial basis and kept on doing improvements as we struggled.

We have created 3 fixed and a temporary branches for each feature
1. Main Production-ready branch
2. ReleaseSanity before production deployment
3. DevelopCurrently developing features
4. Feature branch Local development

git flow, git workflow
Representation of sample git graph with the new git flow. (Abbreviation used, SC: Squash Commit, Feat: feature, c1: commit 1)

Development Phase

Now each developer creates a branch from develop to start developing his/her feature
git checkout -b {{TicketID}}_hello_world

  1. As developers make progress with their assigned tasks, they continually add commits to capture the logical parts completed thus far. This ensures that each developer takes a code backup at the end of the day, preserving their work. Additionally, we create a review request (PR in GitHub) for each feature and have it reviewed by fellow developers. This collaborative review process boosts the developer’s confidence and allows for small tasks to be signed off successfully.
  2. Once a developer completes their development tasks and receives approval for all the commits, they are ready to merge their code with the develop branch.
    But wait, if he directly merges to develop then all the commits from his feature branch will be added to the develop branch and also a merge commit might get created. The history of a develop branch gets cluttered.
Merging Feature to develop
  1. To address this, the developer rebase their branch with the latest develop branch. This ensures that all the feature-related commits are positioned on top of the updated develop branch. Then, they squash all the commits into a single commit, which is subsequently merged with develop. By including the Jira ticket ID in the commit message, the commit linked to the corresponding ticket as well. As a result, all the individual commits are consolidated into one, providing the develop branch with a single commit for each specific feature. This consolidated commit retains its position on top of the develop branch due to the rebase and merge process.

Testing Phase

  1. At the same time, all developers who have completed their tasks will merge their code into the develop branch. This allows QA to initiate testing, enabling multiple QA testers to work in the same environment and evaluate multiple features concurrently. We have successfully overcome this hurdle, accelerating the testing process.
  2. So far, everything is going well. Some features have completed the QA process and are ready for deployment to production. However, there are still some features undergoing QA testing. We aim to release only the features that have successfully completed the QA process.
  3. Developers handpick the commit that is related to a feature, But wait how will you be able to find it? (there might be multiple commits, for fixing any bugs during a QA process).
    Here the ticket id we have added in the commit message comes to the rescue. We will cherry-pick all the commits having that ticket id.
Merging from develop to release
  1. Now all the ready-to-be-released features will be added to the release branch. QA performs a quick sanity of all the features to verify the inter-dependability of the features.
    With this, not everything only the select features are being released t production.

Release Phase

  1. Once done, the release branch will be merged to the main (this will be a fast-forward merge, with no merge commit and the linear history) And the main is all ready to be deployed to production.
Merging from release to main
  1. With all this, we have done a single commit for a feature and also have the linear history, well done!!! But wait, why do we need all of this?
    This was just the happy path when everything worked out fine. What if something goes wrong then let's see how those practices help us now.
  2. Now assume something went wrong on the release branch, because of a particular feature, and you have decided not to release that feature. Now simply you can find the commit by ticket id (mostly you will find those on top only) and revert them. And done. Later you can fix them on develop branch and follow the same release cycle.
    a. Since we had that squash commit, all the code related to a feature was in one place and was easy to revert
    b. Also having a linear history it was easier to find the commit. Recently added items seats on the top and not when they were developed also helpful to revert them, no need to worry about the merge commits

Take-Aways

With this, we have tackled all the issues that we have encountered previously. To finalize this flow we have tried and looked into multiple git best practices. And we have found this a good fit for our team set up and we had stuck to it for a while. We believe there is no one stop solution for everyone, identifying your teams problems and developing a solution tailored for your team would be more efficient.

I would be very glad if you find this blog post useful and knowledgeable. Special thanks to my colleague, Bikash Gupta, who helped me a lot to write this blog post. Please share the blog and leave your comments if you find this git flow helpful or you were able to derive your git flow from it. Suggestions and comments are most welcome.

--

--