DEV Community

Markus Decke
Markus Decke

Posted on

From branches to trunk (a journey)

Preface

In environments where people are used to using some sort of Gitflow variant, the norm is having main, develop, and long-lived feature branches. There are often not enough good automated tests and use-case coverage to deliver with confidence, so branch isolation and friction-creating processes are used to ensure some quality. At least having a DEV stage where builds get deployed after they successfully created a container image is the usual case. This doesn't mean there is an automated release process or additional stage for testing prior to a release, also known as merging into main.

This means the DEV stage can be a moving target for testers, if the first stable stage is the INT stage, where Releases (2 weeks of work) are deployed for delivery towards production. Here, the testing works on a fixed set of features and stable servers, without the surprises of new features popping up when something is merged.

Since Releases happen every 2 weeks, people can be eager to merge instead of waiting another 2 weeks when they are nearly but not yet done, especially clients and project managers, who can get restless. So we get bugs that get caught on INT, and then we need to create hotfixes and test again. If there were merges in between, the fix needs to be cherry-picked, which means the hotfixed Release isn't the same set of features as the current develop branch.

Current setup

Delivery Stages

  • DEV (develop) - develop branch gets deployed after merge (build takes hours)
  • INT (Integration) - main branch gets deployed every 2 weeks after release build
  • ...
  • PROD (Production) - gets deployed 2 weeks after INT

This means the state on INT is not the same; if errors occur, we need to have a hotfix, and this means more friction.
The often-used solution is to have a merge-freeze on develop until Release, to ensure everything on DEV gets tested. So main in the end is the Release branch and has no other function. You could also tag a commit in develop and release that without going through the motions of PRs from develop to main, which is done by hand; this is cumbersome and creates a lot of friction and therefore waste.

A new idea is to have a TST (testing) stage, so that a fixed set can be tested and released.

New setup

Delivery Stages

  • DEV (develop) - develop branch gets deployed after merge (build still needs hours)
  • TST (testing) - a fixed state of develop can be tested and then merged into main
  • INT (Integration) - main branch gets deployed every 2 weeks after release build
  • ...
  • PROD (Production) - gets deployed 2 weeks after INT

Question: How do we get the tested commits into main after new merges into develop?
Answer: More branches!

Branches everywhere?

So now we have develop and main as branches with the new setup, we need to branch from develop with a certain set of commits to merge into main.
One way could be to create a new branch from develop and merge into main, so that we still have PRs and manual actions and waste.
Instead, we could tag a commit and merge the tag into main, which we can do by hand or we can automate.

Moving towards trunk!

Question: If we do this, do we really need main anymore?
Answer: I think not.

Question: Could we instead work and release only develop?
Answer: Yes, let's call it trunk instead of develop.

We could tag a commit in develop and release the tagged commits, that way we don't need an extra branch and manual motions to get the commits into it. Less manual work and friction, less waste.
Depending on your view, we could call it successfully moving towards trunk-based development.

What do you think? Let me know in the comments.

For me next stop in the journey is moving towards continuous delivery :)

Top comments (0)