"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."
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.
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.
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.
We have a main branch, and a develop branch. Feature branches are based on the main branch.
When a developer is happy with their feature branch, they open a pull request to develop, which gets reviewed by another developer and, eventually, merged to develop.
The code in develop gets deployed semi-hourly or on demand to a testing environment, where quality assurance takes on the feature branch.
Eventually, when the testers are happy with the feature branch, it gets merged to the main branch. Main gets deployed to production daily, or on demand. There are no release branches or tags.
Feature branches that take longer are periodically rebased on main (or main gets merged into the feature branch). On rare occasions, hotfix branches are merged directly to main (and immediately, possibly partially, deployed). That code lands in develop via an automatic merge process from main to develop.
The weakness of the model would appear to be that testing practically never happens on the main code branch. I say practically, because we do have a staging environment that reflects the main branch code version, but it's almost unused. It just hasn't been an issue in a decade+ working this way with a team of 8-20 developers. Maybe it doesn't scale to much larger teams?
Someone help me out, is there a name for this model?
It doesn't appear to be gitflow, which IIUC periodically transforms (or merges) the entire develop branch into main branch (we never do this). But it also doesn't sound like it's trunk based development, which doesn't seem to have a develop branch, and also uses versioned releases. We can't be the only ones doing it this way?
1. What is the relationship between the code in the main branch and the code in the develop branch?
2. What assurance does the testing on the develop branch provide that the feature branch is suitable to merge into the main branch?
I mean, presumably you've got main and develop because they need to be different. But then, because they're different, you're never really testing the code that you actually deploy. Superficially, it seems both more complicated and less reliable than trunk-based development.
What am I missing? Why would this way of working be helpful?
Maybe I misunderstood your description, but does 'develop' not ever merge to 'main' directly? Your description sounded like QA could for example test 'develop' which is main + featureA + featureB, give that a green light, and then have new main be main + featureA (which has been never tested). That does sound bit dangerous.
(As an embedded developer, it would be bliss to experience 'develop gets deployed semi-hourly'...)
Gitflow and TBD are just two of the many possible ways to use Git. Several companies (such as yours) use other systems that have no name. And that is fine. We don't need to name every possible variation of a Git model.
> It is important to note that today’s CR-delimited text file systems are blunt instruments compared to the fine-grained directed graphs with fidelity down to class/method history of each of those. It was more like a multidimensional database with cross-cutting tags representing HEAD, or someone else’s important combination of those three. It was omnipresent too - a decision made to move HEAD was instantly available without ‘update’ action to teammates
These stories about Smalltalk and Lisp (machines) sometimes read as if they came from a forgotten, ancient civilization that was way more advanced than ours.
I think it's interesting to note that Google's "default" model now (what's recommend to incoming engineers) is the fully trunk-based monorepo, in a Perforce clone called Piper... But with a Mercurial based interface for actual development.
In your individual checkout you can have arbitrary branching structures, then it just gets squashed down to a linear model when you submit to the monorepo.
It's a bit annoying from a technical POV that there are two separate VCS, but the conceptual model works well IMO.
Reminds me of a friend wondering how he could keep local wip changes without polluting his git repo, or accidentally push WIPs to his colleagues. I suggested adding a personal Mercurial repo to the same folder. I think he was happy with that.
Personally I often have lots of messy WIPs in temporary local git branches. With some rebase, squash and occasional reflog to keep main tidy.
Frequent releases of a main branch to which developers push code (either via other branches, mr's) or direct commits... Thats what it is..
Even if you create a release branch on every release... A tag would also do.. But a tag and a branch are technically quite similar in git... Its mostly fluff
Deploy often, dont have long lived branches. Have your main branch in a deployable state 90% of the time... Hoora youre there
I have the same experience! Trying to introduce the teams I've worked on to TBD and frequent releases, but they don't see any issue with long lived branches and infrequent releases
The article linked is a site all about trunked based development.
>So what is it exactly? Linear history?
The essence is that changes developers make are included into the trunk (main / master branch) as fast as possible. Developers shouldn't be branching off and spending a bunch of time making commits without them being added to to the main branch.
You can run CI/CD on the commits developers want to get rebased onto the trunk.
Point two:
Alternatives to source control branches are dark launches, branch by abstraction and feature flags.
Point three:
The best results that I have had on developing systems were doing exactly that. You need more discipline (like make sure that you run test and linters locally), but my experience is that makes the whole process easier.
CI is continuous integration, there is nothing continuous to coding on your branch and merging after a few days.
In my experience, working primarily based on integration branches, as opposed to working on master and cherry-picking back into integration branches, provides some short term benefits but is net negative in the long term.
1. People stop caring about master. Then master breaks and nobody fixes it. This is a problem if not _everyone_ is on the integration branch, e.g. if there is a single small team working on a feature for the next+1 release that needs master: they can't fix all the breakage from all the other teams, and they can't get the other teams invested in not breaking master. This ruins that teams productivity, which makes development of larger scale features much more costly. Even if no team needs master, leaving master broken and coming back to it later makes those fixes more costly.
2. Regressions: people mark bugs closed as soon as it is fixed in the integration branch. Then the fix never makes it into master, and you get regressions on the next+1 release. Automatic forward merge (always immediately and automatically merge release/n to release/n+1 [...] to master) as supported by e.g. Bitbucket can help with this, at the cost of the occasional merge conflict(s) and less control in case some fixes actually should not go into a specific intermediate release.
Release integration branches bring the behaviour of big releases. The bigger the release, the bigger the risk, therefore the less you want to do it.
With release integration branches you not only integrate for release (which the bigger the release, the more difficult it is), but also now you have to integrate back from release into main (because bug fixes and what not). The longer that you have had that integration branch, the more likely that you have move forward the main code and the more difficult then becomes the back integration. So you end duplicating the effort.
I’ve personally never worked on one much, but you have to keep (at least) two branches active for a release. Main development would happen on a shared feature branch (to be larger merged), but you also need to keep master/main updated with bug fixes and other changes that aren’t release gated.
More around versioning itself, but having a single big merge is a single high risk point. Releasing everything all at once is more likely to have larger and more severe bugs than many small releases, even if you gate the deployed releases behind feature flags.
Nothing, but you have to do it right. If you look at Linux, you'll notice there is no central git server with a master branch that people push to. The most stable development branch (in addition to the LTS branches), is whatever Linus Torvalds has chosen to merge to his personal master branch. He cuts a new release from there roughly every two months. Whatever is on that branch is the next version of Linux.
That's integration branches done properly. Linux releases are cut from that branch. Literally everything else is an integration branch and it won't get pulled (you don't get to push) by Linus Torvalds until it merges cleanly and passes all the scrutiny that he and his people apply to incoming changes.
Very few companies work like this of course. So instead you get people working on their pet branches and ignoring upstream changes. It's stupid. All you are doing is deferring integration work. Integration work scales exponentially relative tot he amount of change. So, the longer you wait, the worse it gets. The flip side is that having branches means you can distribute the integration work across those branches. And if each branch only has a small delta relative to the main branch, the collective integration work load decreases. The way you keep the delta small is by pulling upstream frequently and staying on top of the upstream changes. If you fall behind, it becomes a problem. And it's exclusively your problem.
Linux doesn't have issues with integration work on the main branch: you are either compatible with upstream and ready to merge or you won't get pulled in. It's that simple. That's why Linus Torvalds can release a stable release regular as clock work. You don't get to stamp your feet and whine about how important your branch is. You do the integration work before your changes are pulled in and it's exclusively your problem to make that happen. So people, integrate upstream changes often and Linus keeps unstable changes out of upstream. They front load all the integration work before anyone even talks to Linus Torvalds. Done right, this scales to an ecosystem with thousands of contributors from a multitude of companies across the globe. It works by distributing the integration work across the ecosystem.
This can work in large companies too. But you have to do it properly and with intent. Pull requests are pretty popular for a good reason: they work the same way. If you have to have long lived branches, somebody needs to worry about those staying in sync with upstream. If that doesn't happen, you have a problem waiting to happen.
It’s a giant pita to manage those if you have many in-flight on a reasonably complex codebase (lets say 500k-1M loc). If you’re a saas you’re probably not getting many of the benefits either
You can save some time by getting rid of them. It forces a team quite strongly to a method of working that is a LOT faster but many devs find the relentless pace quite challenging. There’s an easy way to tell the approaches apart - if you have 5 devs does your team have 4-10 items in flight usually? if so that’s a team on the slow and steady path. if you have a team of 5 and you all work on the same thing at the same time then the pace can be really quite impressive.
Release branches have a place where you are releasing software and supporting multiple different release versions for different clients, because you need to be able to bug-fix older versions and merge fixes forward rather than just fix current and re-release into your own system.
If you only ever give a shit about ‘latest’ then you don’t need to bother with them. IMHO.
At that I'm kinda waiting for someone to advertise "just putting each release in tarball with date in name" as the new hot in source control. Hell, let's go back to CVS while we're at it
It's really important to point out that Google's monorepo works in large part because they have spent 100s of engineering years on their build and deployment tools.
It would be very hard for a large company to adopt their monorepo because you'd have to replicate their tools.
Just in case anyone was thinking of just copying Google...
In regards to the subject I think it is also important for the developers to understand and agree upon what the mainline (master/main/etc.) branch represents. For me it should contain only commits/changes which result in the new HEAD properly working and having a bug fixed and/or feature added.
So the feature/bug/etc. branches can contain multiple commits which are helpful for the developer(s) that's working on it but it all should be squashed into a single one during merging into master.
In short the history noise in master should be kept in check and reduced as much as possible which makes e.g. bisect easier as we don't take into account pointless commits and the history is cleaner. Problem is many think "more is better" and they end up with branches that are much more complicated to work with and reason about.
Trunk-based development reminds me of Agile Development: the drawbacks mostly accrue to the developers while the benefits mostly accrue to the managers.
The Agile manifesto was created by devs, for the benefit of creating software. Everyone gets the benefits.
After having used release and feature branches, and trunk based development, as a developer I see mostly benefits (there are some drawbacks, there is no perfect technique) with trunk based development.
[+] [-] agentjj|3 years ago|reply
"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."
[+] [-] osigurdson|3 years ago|reply
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.
[+] [-] Cthulhu_|3 years ago|reply
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.
[+] [-] hsn915|3 years ago|reply
[+] [-] kkapelon|3 years ago|reply
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
[+] [-] bacro|3 years ago|reply
[+] [-] morsch|3 years ago|reply
When a developer is happy with their feature branch, they open a pull request to develop, which gets reviewed by another developer and, eventually, merged to develop.
The code in develop gets deployed semi-hourly or on demand to a testing environment, where quality assurance takes on the feature branch.
Eventually, when the testers are happy with the feature branch, it gets merged to the main branch. Main gets deployed to production daily, or on demand. There are no release branches or tags.
Feature branches that take longer are periodically rebased on main (or main gets merged into the feature branch). On rare occasions, hotfix branches are merged directly to main (and immediately, possibly partially, deployed). That code lands in develop via an automatic merge process from main to develop.
The weakness of the model would appear to be that testing practically never happens on the main code branch. I say practically, because we do have a staging environment that reflects the main branch code version, but it's almost unused. It just hasn't been an issue in a decade+ working this way with a team of 8-20 developers. Maybe it doesn't scale to much larger teams?
Someone help me out, is there a name for this model? It doesn't appear to be gitflow, which IIUC periodically transforms (or merges) the entire develop branch into main branch (we never do this). But it also doesn't sound like it's trunk based development, which doesn't seem to have a develop branch, and also uses versioned releases. We can't be the only ones doing it this way?
[+] [-] civilized|3 years ago|reply
1. What is the relationship between the code in the main branch and the code in the develop branch?
2. What assurance does the testing on the develop branch provide that the feature branch is suitable to merge into the main branch?
I mean, presumably you've got main and develop because they need to be different. But then, because they're different, you're never really testing the code that you actually deploy. Superficially, it seems both more complicated and less reliable than trunk-based development.
What am I missing? Why would this way of working be helpful?
[+] [-] unknown|3 years ago|reply
[deleted]
[+] [-] dezgeg|3 years ago|reply
(As an embedded developer, it would be bliss to experience 'develop gets deployed semi-hourly'...)
[+] [-] kkapelon|3 years ago|reply
[+] [-] TeeWEE|3 years ago|reply
I would call it trunk based development, since feature branches are short lived.. Most MR are just 1 or 2 commits. Just part of our review process.
[+] [-] loupol|3 years ago|reply
[+] [-] dgb23|3 years ago|reply
These stories about Smalltalk and Lisp (machines) sometimes read as if they came from a forgotten, ancient civilization that was way more advanced than ours.
When does the renaissance come?
[+] [-] bhaak|3 years ago|reply
I always wondered if git would have been as popular if it wouldn't have come from Linus.
[+] [-] paul_h|3 years ago|reply
[+] [-] malkia|3 years ago|reply
[+] [-] igouy|3 years ago|reply
[+] [-] drowsspa|3 years ago|reply
[+] [-] bjackman|3 years ago|reply
In your individual checkout you can have arbitrary branching structures, then it just gets squashed down to a linear model when you submit to the monorepo.
It's a bit annoying from a technical POV that there are two separate VCS, but the conceptual model works well IMO.
[+] [-] flurdy|3 years ago|reply
Personally I often have lots of messy WIPs in temporary local git branches. With some rebase, squash and occasional reflog to keep main tidy.
[+] [-] xen0|3 years ago|reply
[+] [-] TeeWEE|3 years ago|reply
Frequent releases of a main branch to which developers push code (either via other branches, mr's) or direct commits... Thats what it is..
Even if you create a release branch on every release... A tag would also do.. But a tag and a branch are technically quite similar in git... Its mostly fluff
Deploy often, dont have long lived branches. Have your main branch in a deployable state 90% of the time... Hoora youre there
[+] [-] bob1029|3 years ago|reply
With a little bit of extra process (i.e. enforce that unit tests succeed on proposed merge items), you can get very close to 100% for most projects.
[+] [-] 4pkjai|3 years ago|reply
[+] [-] mailund|3 years ago|reply
[+] [-] unknown|3 years ago|reply
[deleted]
[+] [-] IshKebab|3 years ago|reply
Edit: I read the first hit from CircleCI and I am none the wiser. The article seems to suggest it could be any of these things:
* Having a main (`master`) branch. But literally everyone except maybe Linux developers does this.
* Not using branches? Which sounds awful.
* Pushing directly to `master` and then running CI/CD! This is insane; does anyone really do this?
So what is it exactly? Linear history?
[+] [-] charcircuit|3 years ago|reply
>So what is it exactly? Linear history?
The essence is that changes developers make are included into the trunk (main / master branch) as fast as possible. Developers shouldn't be branching off and spending a bunch of time making commits without them being added to to the main branch.
You can run CI/CD on the commits developers want to get rebased onto the trunk.
[+] [-] MiyamotoAkira|3 years ago|reply
Point three: The best results that I have had on developing systems were doing exactly that. You need more discipline (like make sure that you run test and linters locally), but my experience is that makes the whole process easier.
CI is continuous integration, there is nothing continuous to coding on your branch and merging after a few days.
[+] [-] convolvatron|3 years ago|reply
[+] [-] Ao7bei3s|3 years ago|reply
1. People stop caring about master. Then master breaks and nobody fixes it. This is a problem if not _everyone_ is on the integration branch, e.g. if there is a single small team working on a feature for the next+1 release that needs master: they can't fix all the breakage from all the other teams, and they can't get the other teams invested in not breaking master. This ruins that teams productivity, which makes development of larger scale features much more costly. Even if no team needs master, leaving master broken and coming back to it later makes those fixes more costly.
2. Regressions: people mark bugs closed as soon as it is fixed in the integration branch. Then the fix never makes it into master, and you get regressions on the next+1 release. Automatic forward merge (always immediately and automatically merge release/n to release/n+1 [...] to master) as supported by e.g. Bitbucket can help with this, at the cost of the occasional merge conflict(s) and less control in case some fixes actually should not go into a specific intermediate release.
[+] [-] MiyamotoAkira|3 years ago|reply
With release integration branches you not only integrate for release (which the bigger the release, the more difficult it is), but also now you have to integrate back from release into main (because bug fixes and what not). The longer that you have had that integration branch, the more likely that you have move forward the main code and the more difficult then becomes the back integration. So you end duplicating the effort.
[+] [-] TheGeminon|3 years ago|reply
More around versioning itself, but having a single big merge is a single high risk point. Releasing everything all at once is more likely to have larger and more severe bugs than many small releases, even if you gate the deployed releases behind feature flags.
[+] [-] jillesvangurp|3 years ago|reply
That's integration branches done properly. Linux releases are cut from that branch. Literally everything else is an integration branch and it won't get pulled (you don't get to push) by Linus Torvalds until it merges cleanly and passes all the scrutiny that he and his people apply to incoming changes.
Very few companies work like this of course. So instead you get people working on their pet branches and ignoring upstream changes. It's stupid. All you are doing is deferring integration work. Integration work scales exponentially relative tot he amount of change. So, the longer you wait, the worse it gets. The flip side is that having branches means you can distribute the integration work across those branches. And if each branch only has a small delta relative to the main branch, the collective integration work load decreases. The way you keep the delta small is by pulling upstream frequently and staying on top of the upstream changes. If you fall behind, it becomes a problem. And it's exclusively your problem.
Linux doesn't have issues with integration work on the main branch: you are either compatible with upstream and ready to merge or you won't get pulled in. It's that simple. That's why Linus Torvalds can release a stable release regular as clock work. You don't get to stamp your feet and whine about how important your branch is. You do the integration work before your changes are pulled in and it's exclusively your problem to make that happen. So people, integrate upstream changes often and Linus keeps unstable changes out of upstream. They front load all the integration work before anyone even talks to Linus Torvalds. Done right, this scales to an ecosystem with thousands of contributors from a multitude of companies across the globe. It works by distributing the integration work across the ecosystem.
This can work in large companies too. But you have to do it properly and with intent. Pull requests are pretty popular for a good reason: they work the same way. If you have to have long lived branches, somebody needs to worry about those staying in sync with upstream. If that doesn't happen, you have a problem waiting to happen.
[+] [-] dilyevsky|3 years ago|reply
[+] [-] CraigJPerry|3 years ago|reply
[+] [-] Nursie|3 years ago|reply
Release branches have a place where you are releasing software and supporting multiple different release versions for different clients, because you need to be able to bug-fix older versions and merge fixes forward rather than just fix current and re-release into your own system.
If you only ever give a shit about ‘latest’ then you don’t need to bother with them. IMHO.
[+] [-] jenadine|3 years ago|reply
[+] [-] jchw|3 years ago|reply
[+] [-] ilyt|3 years ago|reply
[+] [-] jedberg|3 years ago|reply
It would be very hard for a large company to adopt their monorepo because you'd have to replicate their tools.
Just in case anyone was thinking of just copying Google...
[+] [-] margorczynski|3 years ago|reply
So the feature/bug/etc. branches can contain multiple commits which are helpful for the developer(s) that's working on it but it all should be squashed into a single one during merging into master.
In short the history noise in master should be kept in check and reduced as much as possible which makes e.g. bisect easier as we don't take into account pointless commits and the history is cleaner. Problem is many think "more is better" and they end up with branches that are much more complicated to work with and reason about.
[+] [-] fwlr|3 years ago|reply
[+] [-] fallbackboy|3 years ago|reply
[+] [-] MiyamotoAkira|3 years ago|reply
After having used release and feature branches, and trunk based development, as a developer I see mostly benefits (there are some drawbacks, there is no perfect technique) with trunk based development.
[+] [-] nl|3 years ago|reply
Google's trunk-based monorepo approach is a developer-centric approach seeming primarily driven by dependency management concerns.