Git Flow Rethink

Revaluating the meaning of Continuous in CI/CD

As a developer, I have spent years embracing the Git Flow branching methodology. It has served me well, providing structure and clarity when working with version control and collaborating with others. Moreover, it has served as an excellent model for effective communication among developers. However, the world of software development and DevOps has been evolving at an unprecedented pace over the past few years.

The challenge I face is how to adapt and evolve my practices to leverage the efficiencies offered by modern DevOps tools. Instead of discarding the tried-and-true principles and starting anew, what if we could leverage the wisdom gained from years of employing Git Flow and apply it to harness the capabilities of today's DevOps tools?

Git Flow Recap

The Git Flow branching methodology, created by Vincent Driessen and popularized through his blog post titled "A successful Git branching model" , has been widely adopted by software development shops as the formal way to manage changes. Its structured approach provided a clear workflow for version control and collaboration. It has served me well as my go-to branching model for many years. But as we embrace the power of continuous integration and deployment, some of the aspects of Git Flow seem to introduce unnecessary ceremony into the development process.

In a recent update to the original blog post, Vincent Driessen states:

If your team is doing continuous delivery of software, I would suggest adopting a much simpler workflow instead of trying to shoehorn git-flow into your team.

Rethinking Git Flow

I propose that we take a fresh perspective on the Git Flow branching strategy. Let's explore ways to enhance our processes without forsaking the strong foundation we've established. As we observe the transformation of the software development landscape, we need to acknowledge that the primary concerns that Git Flow addressed might not be as prevalent in today's context. However, there is a clear path to adapting and evolving our practices to embrace the efficiencies provided by modern DevOps tools.

A pivotal shift in my approach has been the embrace of continuous integration and deployment (CI/CD) practices. I have discovered that by capitalizing on the potential of CI/CD, I can streamline workflows while upholding the essential measures of quality assurance. It's akin to a delicate balancing act: incorporating the strengths of Git Flow and seamlessly integrating them with the capabilities of contemporary tooling.

After using the model for years, I took a step back and had to ask if git-flow was the best branching model for my team. Or was I following it because it was the way I had always done it? In many projects, I found that I did not need much of the ceremony of Git Flow. On my projects, we did not have multiple teams working in the same repository on features that spanned multiple iterations. Web applications that continuously improve, did not need the rigor or ability to quickly restore older product versions.

After many discussions on the merits of Git Flow, particularly the use of permanent development and main branches and branch creation for each release with a merge back into both develop and main branches has created tasks that seem to add more form than substance. The DevOps tooling does not support the Git Flow branching model out of the box, requiring manual intervention and enforcement via processes and procedures. This manual intervention can lead to inconsistencies.

Branch Policies and Protection

In the Git Flow branching model, temporary branches such as release and hotfix branches play a crucial role in managing specific features or addressing critical issues. However, implementing branch policies on these temporary branches can pose challenges, particularly in certain DevOps platforms like Azure DevOps. The difficulty arises from the manual application of default and comparing branch attributes to each new branch, which can result in release and hotfix branches lacking the same level of protection as permanent branches.

What is in Production?

One of the challenges with the traditional Git Flow branching model is determining what exactly is in production by simply looking at the repository. In Git Flow, temporary branches are often created for releases and hotfixes, which are subsequently merged back into the development and main branches. However, in many cases, the release or hotfix branch remains open after deployment, allowing for quick fixes if necessary. This practice can make it difficult to identify the exact state of the production environment by examining the repository alone.

The ambiguity surrounding what is in production becomes a concern, particularly when trying to trace back specific changes or identify the codebase associated with a particular release. Without clear indicators or references, developers and team members may find it challenging to pinpoint the exact code deployed in the production environment. This lack of visibility can hinder troubleshooting efforts and make it harder to establish a comprehensive understanding of the software's state.

False Sense of Security

The Git Flow branching model's reliance on two branches, develop and main, can lead to a false sense of security. In this model, any commit merged into the develop branch will become part of main branch and production. However, this means that the develop branch requires the same level of control and scrutiny as the main branch. Unfortunately, the develop branch often becomes a temporary workspace for ongoing development, making it susceptible to inconsistencies and lax code quality controls. Additionally, the lack of branch policies on temporary branches complicates maintaining code integrity throughout the development process.

A Single Permanent Branch

In response to the limitations and challenges posed by Git Flow, an alternative approach gaining momentum is the adoption of a single-branch strategy. This approach involves using a single branch for all pull requests, streamlining the development process and simplifying the codebase management. But how can this single-branch approach overcome the weaknesses of Git Flow and ensure efficient and controlled development?

The answer lies in leveraging the power of modern DevOps tooling. The tooling available today provides robust features and automation capabilities that can offset the manual processes and policies traditionally required in Git Flow. Let's explore how these tools can address the weaknesses and enhance the efficiency of the single-branch approach.

Automated branch policies

DevOps platforms such as Azure DevOps, GitHub, and GitLab offer automated branch policies. These policies can be easily configured to enforce code reviews, unit tests, and other quality checks for every pull request. By configuring these policies on your permanent branch, developers can focus on coding while the tooling ensures the necessary quality assurance measures are in place.

Continuous Integration and Deployment (CI/CD) pipelines

Modern CI/CD pipelines provide seamless integration with version control systems. They can be configured to trigger automated builds, tests, and deployments for every pull request and merge into a single branch. This ensures that code changes are continuously integrated, validated, and deployed to development , staging, and ultimately production environments, enabling rapid feedback loops and early identification of issues.

Versioning

You can configure your project to increment the version upon every build. This means you can look at the assemblies and easily know when they were built and what version they are. This is a huge benefit when trying to determine what is in production. With a single-branch approach, the tooling can facilitate automated versioning, tagging, and release creation based on specific commits within the single branch. This simplifies the process of identifying what is in production and enables teams to track and manage releases more effectively.

By embracing the single-branch approach and utilizing the advanced tooling available, we can optimize our development processes and mitigate the weaknesses associated with Git Flow. The automated branch policies, CI/CD pipelines, and release management features empower teams to enforce quality controls, ensure continuous integration and deployment, and streamline the identification of code in production.

The reliance on manual processes and policies in Git Flow can be significantly reduced. This enables developers to focus on delivering value more rapidly without sacrificing code quality. By leveraging the advancements in DevOps tooling, the single-branch approach becomes a powerful strategy for efficient and controlled software development, ultimately leading to improved productivity and software delivery.

This rethink of the Git Flow branching model opens up new possibilities for teams to innovate, collaborate, and accelerate their development processes. It liberates developers from unnecessary complexities and allows them to concentrate on what truly matters—building great software.