GitHub Flow vs. OneFlow: Which Git Workflow Works the Best for You?

A simple Git repository strategy I use in my teams

Nuno Barreto
Better Programming

--

Introduction

For many years I have been using what everyone calls the Git Flow model to organize code branches, environments, and deployments. Although it was not the intention of the author, many people I have met have become quite dogmatic about it. The author himself points to that in a 2020 “looking back” note.

The problem with accepting dogmas, is that we reach a point where we believe that this is the only way of doing it, and we stop looking for alternatives, or possible improvements.

Problems

While Git Flow is still quite useful for the type of software it was created for. As its’ author Vincent Driessen said in 2020: “If (…) you are building software that is explicitly versioned, or if you need to support multiple versions of your software in the wild, then Git Flow may still be as good of a fit to your team as it has been to people in the last 10 years”.

The teams I have led were more focused on developing Web Apps and APIs, where the Git Flow model adds unnecessary complexity. In most of those projects, branches master and develop are highly redundant, creating many merge problems between branches, and creating a spaghetti git history that is hard to follow. Not to mention how many teams even add a stage branch on top of that.

If we think about the current practices of CI / CD, it becomes clear that all of this added effort and problems became just unnecessary paperwork that steals the joy and productivity of any developer.

The Path I Took

I got a bit tired of the constant merge conflicts (and developers' conflicts resulting from that) and decided to look into what other teams were doing.

I started with the big ones and was surprised to learn that Google was using a mono repository with just one long living branch: master. And with real CI / CD, every commit is a release!

That made me question why I was using such complex models. The first time I mentioned this to one of my teams, there was a mix of “It can’t be true!” with “If we did that our products would be always broken!”. It made me realize that the main reason why we create complex systems with more and more steps is fear! Many projects do not have the necessary fail-safes in place (Automatic testing, code reviews, etc).

That’s when I started to investigate more, and a lot based on the OneFlow model decided to find a middle ground that worked for most teams. For simple projects what I use is the GitHub Flow model, with a real CI / CD process: Only a master branch and branches are created for features and bug fixes that are merged directly to the master when complete.

When the team is bigger, and the project more complex (monolith anyone?), then I apply my simplified version of the OneFlow model with a weekly release. This is the model I describe here.

OneFlow Model

This is the model I use when the project is complex and/or the company/client wants or needs to have bigger control on what is released. This is normally linked to one or more of:

  • Old monoliths that do not have proper automatic testing in place, and rely on QA teams (the most common case).
  • Lack of trust by the Business team because of what happened in the past (normally linked to monoliths, or too inexperienced badly paid teams).
  • Products where the consequences are quite serious if something goes wrong (think banking, hospitals, military, etc).

Branches

You may not need all these types of branches, but the main point is that there is only one long living branch: master.

  • master: The only eternal branch. The master branch is considered the main branch, and should always be in a release-ready and production-ready state.
  • release/x.y.z: A release that is being prepared to be launched. Once tagged with the version, it is released. It is then merged to master.
  • feature/XYZ-1234: A feature linked to a Story or Task ticket. Once complete, it is merged to master.
  • bugfix/XYZ-1234: A fix linked to a high, medium, low, or lowest Bug ticket. Once complete, it is merged to master.
  • hotfix/XYZ-1234: A fix linked to the highest Bug ticket. It is taken from the commit with the most current version tag. Once tagged with the version, it is released. It is then merged to master.

Pull Requests

Before a feature or a bug branch is merged to master, a Pull Request must be created by the developer, and it should only be merged once the Pull Request has been approved by at least 2 developers.

It is important to have the code well tested before merging, which means having automatic testing with high code coverage and depending on the team, maybe approved by both the Product Owner and the QA team.

Environments

The fact that we have fewer branches, does not mean that we have fewer environments. Depending on how your team is organized, you may need all of these environments or not. Check for the real need. But automate the whole process.

  • Production: Live environment, where your clients use the product.
  • Staging: production-like environment used for the QA tests before launch. No need for this if we are doing real CI / CD.
  • Development: Used for development when not possible or desirable to launch the complete environment locally. A good example is a frontend developer wanting to use an API endpoint that was just developed. Can also be used by QAs or POs for special testing.
  • Testing: Used for running automatic tests. Created, ran and destroyed at each commit. Normally as part of the CI / CD process.
  • Feature: A bigger feature that needs to be tested separately. Can be used by PO for validation. It is created on-demand whenever necessary and destroyed after no longer needed.

GitHub Flow Model

When the team and/or the project are small, I use the Github Flow model. That means that every merge on master becomes a release, with real-time CI / CD happening.

Compared to the OneFlow model above, I remove the need for release branches and the version tagging complexities associated with it. I still add version tags, but they are done directly on master.

Nothing wakes you up more than the feeling of releasing something directly in production whenever you merge to master. YOLO :)

Results

So, how has this been working for me and my teams? Very well, I have to say. There is always some fear and resistance on the teams whenever I propose this, but the results have been great:

  • Happier developers feel they can focus more on development and less on bureaucracy and problems.
  • Fewer personal conflicts are caused by merge conflicts.
  • Less human error (Fewer opportunities to merge to the wrong branch and create merge conflicts).
  • A process is easier to automate for the DevOps team.
  • A process is easier to understand by Business departments.

But it always starts with talking with the people and showing the benefits of the alternatives. And then inviting them to be brave and try it. It’s ok to be afraid, but do not let fear stop you from advancing to something better for you and your team.

Start with OneFlow, with weekly or bi-weekly releases. You are still 100% safe there, nothing gets released unless you decide. And as you and your team gain trust in the process, and automates it better and better, one day you’ll be able to decide to go full auto on the release process for some of your products using GitHub Flow. No need to rush it.

References

--

--