Hacker News new | ask | show | jobs
by agentjj 1227 days ago
It's rather funny.

"Trunk-based development" is essentially counter-marketing to Gitflow. Before Gitflow, trunk-based development was so routine it didn't need a proper name or website.

Gitflow has the "interesting" properties of being more complex than release-ready trunk-based setups, while (in most contexts) decreasing quality, and delivery speed.

Unfortunately, Gitflow is very appealing to mediocre managers who want to point to a website and some pretty pictures and say "we do that" (thus, alleviating themselves of any actual engineering or contextual thinking). So the counter-marketing is helpful, but it feels rather ridiculous how the software world is so susceptible to these trends.

It reminds me of the Alan Kay quote, "programming is a pop culture."

5 comments

I prefer do-what-makes-sense-flow. However, hard to write a book or sell tickets to conferences on such an approach. Branching "strategy" is probably the least impactful thing on any project but it is easy to have an opinion about. For this reason we end up focusing on that instead of the hard/mucky stuff.

Having said all of this, I do think git-flow is a little complex as a general procedure. For the project I am working on now feature toggles are often better but branches (even longer lived ones) in some circumstances can be optimal.

The bottom line is some things are better in-than-out while others are better out-than-in. Let's stop being dogmatic about it.

For those who like me didn't know, "feature toggles" means that you implement the feature on trunk, but with some kind of flag that disables the feature until it has been thoroughly tested and is ready for release. It baffles me that we require special terminology to describe what is just common sense. Have we invented so much extra complexity that keeping it obvious and simple is a special case?
It isn't bad compared to "branch by abstraction", which sounds incredibly complicated until you realize that you have probably already used this many times without realizing: use an interface, implement a new version of it, use a toggle to determine which one to use... eventually deprecate the old one.

Can we at least agree to reject the academization of this one and simply refer to all config-time optionality as a "toggle".

Gitflow is more complex for sure (although there's less-complex alternatives that work just as well, but that aside), but it's with reason and allows for parallel maintenance of released versions in more traditional applications where multiple versions may be alive, e.g. non-evergreen desktop applications and server software.

It's added complexity and it has a cost, but there are good reasonings for it. Trunk-based and not-gitflow is fine for SaaS services or web applications I'm sure, the things that CAN be deployed in a continuous deployment fashion.

Gitflow merges everything to a linear 'master' branch, from which releases are tagged. That means you can't create new 1.x releases after 2.0 has been tagged.

In TBD you'd have most new development happening on trunk, but there's no reason you can't spin off a release/v1.x branch as well as a release/v2.x branch from the trunk. The point is just that these shouldn't merge back into trunk -- they're spun off forever.

You can cherry-pick patches onto release branches, but you need to figure out what that means on a case-by-case basis. There's no guarantee that the patch will apply cleanly, and there's no guarantee that it will make sense, even if it does apply cleanly. No branching strategy can fix this for you.

Eh - it's really a conversation about how dogmatic you want to be here.

You have all the info you need with gitflow to go back to the state of a specific release, and then create additional releases based on that state.

Basically - there's nothing stopping you from going back to your 1.0 tag well after release 2 or 3 or even 4 are out, and then branching from there and creating a new 1.x release.

You have a wrinkle left over afterwards, since you now need to determine if any of those 1.x changes should actually make it back into develop (and this is really a case by case question) and you also (at least in my opinion) need a really valid reason for creating the extra maintenance of this wrinkle, but large paying customers can sometimes be a valid reason.

I think you have to tackle the same problem with TBD - there are certainly times when "spun off forever" is acceptable, but there are times when you genuinely want some of the work done on an old release to make it back into the mainline trunk.

---

Long story short... just prefer not to be dogmatic about these decisions and you can generally make most things work. Your customers don't give a flying fuck how you handle branches, and it should really be a consequence of what the team needs right now, rather than a "set in stone" process.

I agree about being pragmatic and doing what the business needs are at the moment!

But that's also why I argue for having less process up front and creating it as needed. The master branch exists solely for the aesthetic reason of having a linear history from version to version. This is obviously incompatible with a non-linear version history.

Simplify the initial process by getting rid of master and tagging directly on the release branch.

In fact, the merge from release branch to master is a bit suspicious. I'd expect the contents of the merge to be precisely the contents of the release branch, regardless of what was on master previously. If not, what am I releasing?

Yup - I agree. I think we'd get along just fine :)

It can be nice to generate release notes from the commits in the merge between the latest release and master, but you can honestly get the same info in a variety of ways (and depending on the team - it may be particularly noisy)

Basically - I think as long as tagging is happening somewhere, and that tag reflects the actual code released, I don't really have a strong preference on the branching around the process. Sort of an implementation detail that doesn't matter that much.

Gitflow is pretty much a traditional, decades-old, trunk plus release branches model, but with an extra branch that does nothing but receive merges, and the names switched around. Well, and feature branches live longer than in TBD (where an implicit feature branch exists on a developer machine between pulling and pushing). It's 95% a different way of describing an age-old workflow.
Explain why trunk-based cannot have multiple live release branches.
Because then it stops being "trunk-based development" but unholy hybrid of few approaches.

There is no notion of multiple stable releases getting patches in trunk based development.

Nonsense. Multiple release branches are a perfectly normal part of TBD. See:

https://trunkbaseddevelopment.com/branch-for-release/

Note in particular "the CI pipeline that guards the trunk is going to be duplicated to guard active release branches too" - branches plural.

Why do you think this? There is nothing about trunk-based development that rules out having several live release branches. Google is the poster boy for TBD in the article, and in their main monorepo there are always numerous live release branches but it is still trunk-based. Fixes go into main and are down-integrated to the releases.
Can't get people to accept any idea now a days if there's no website dedicated to it.
Gitflow is very appealing to people that have multiple versions of the same thing in production. I would even consider it essential in such cases.

The typical example is a B2B company that maintains one prod deployment per customer and each customer wants a completely different release schedule

There are also several people that don't really care about release speed

I don’t get it. Nothing about trunk-based prevents multiple live release branches. It’s the direction of development that changes. You never work on the release branch, but you do down-integrate relevant changes from trunk to release.
Customer A wants feature X now. Customer B wants feature Y now. X and Y are conflicting with each other.

You can either spend 4x the amount of time to make them compatible (and still follow TDB) OR spend x time and just deliver to each customer the respective feature only (and no longer follow TBD)

Your whole argument hinges on "are conflicting with each other". I am confident that in many cases I would be able to put the X stuff in x_lib and the Y stuff in y_lib and link two different binaries for them, from head.
"put the X stuff in x_lib and the Y stuff in y_lib" is exactly what takes 4x amount of time

Also this process can continue. In the next iteration you have will 3 incompatible features with the same or different customers.

If you use different branches you can always to go to branch X and know exactly what is deployed on customer X.

In your case the only way to recreate what customer X has is to find the proper combination of libraries that you have shipped to them so far.

Imagine I am a developer and want to do a hotfix for a specific customer. I can just do git checkout branch-of-customer and start working. Isn't the process more difficult with your approach?

This is one of the points where the dogma breaks down.

If trunk has changed substantially from the release branch where the patch is required, you can't cherry-pick and you need to work on the branch.

I of course cannot support dogma when it comes to software development. Pragmatism carries the day every time. But rare cases where a fix from head has to be edited to apply on a release branch does not invalidate the other advantages of trunk-based development, and there are ways to avoid the need to do such edits, including making sure that the pace of retirement of old releases is consistent with the pace of development on mainline.
Yes, agreed. Unfortunately as with most software development process fads, most of the TBD advocates I've met fail to understand that nuance.

Mind you, I've been "doing TDB or a variation of it," and advocating for it for as long as I can remember. Still, as soon as TBD was given a name and evangelists started sprawling and calling me a heretic because I favoured pragmatism in many instances, I started disliking the dogma as a whole.

I'm fine with using it as a discussion starter. Always look at principles and outcomes though. If the dogma gets in the way, discard the dogma and do what will work given your teams, their culture and their maturity.

Question: For mobile apps, wouldn't gitflow be more suitable, since the app is only released after app store validation? The release branches here seem to match well this purpose. Just to curious to know how trunk-based development is applied in practice for mobile apps.
That release branches make sense in some circumstances does not mean one has to take all of 'git flow' on board. This is the problem that the comment you are responding to notes. One should design a branching strategy depending on what one needs to do and not do things because one has a branching strategy.
True but I have seen people claim TBD should be used in all cases and I was trying to get some insights on how people use TBD for mobile apps as using release branches is not TBD as well.
I love TBD. But it has its places. For mobile apps I've used (and would use) release branches. You have a hard requirement on the way that app stores work.

You can still do TBD for most of the development of new features, though.

We always worked in a way where the master branch is running a regular release train into our internal / beta / preview release (depending on company and audience size). Both major play stores provide ways of automatically and regularly releasing builds with minimal review (internal channel, TestFlight, Firebase app distribution. etc). Those channels are fed directly from master and used for testing, showing demos to customers and other bleeding edge use-cases.

One of the builds is then chosen as an "actual release" and promoted to the release channel in the store - the commit with the cutoff is tagged in Git.

If, for some reason, a patch needs to be applied to that exact build, you can always branch off from that tag and apply patches. But that was usually avoided and a newer, fixed, build promoted as release instead. I think we had to backpatch things less than once a year and only in very rare cases.

# We always worked in a way where the master branch is running a regular release train into our internal / beta / preview release (depending on company and audience size).

Care to elaborate how you decide if it is an internal / beta / preview release? Some kind of tagging strategy or are all generated at the same time?

Oh we just chose one (I just used slashes because different systems used different names). In reality we had only two builds - the "daily" preview that was built automatically when PRs merged and were used by developers and beta testers (we published to beta channel) and the actual releases that went to production (which were market with git tags).
Release branches are fine (mobile apps, sure... web apps, probably not). Again, context is key.

You can still integrate to trunk as one would expect in TBD, no need for the delayed integration in Gitflow.

A common practice I see with mobile teams is they will create a 'release/x.y' branch sourced from trunk as part of their release routine (at some regular cadence, like 2-weeks).

If they need to (surgically) apply a hotfix, they can apply it to the release branch. Since the app store review process makes deploying immediate fixes impossible, a stronger emphasis on staging/RC QA is good as well.