My problem with trunk based development is I feel like people treat it as the solution to a problem that is fundamentally a developer culture problem.
You need to commit small changes, frequently, which requires you to only change small sections of the code and make incremental changes, something which can be a difficult habit to get used to.
This is really the main benefit of trunk based development, and it’s something you can get with feature branches as well, you just have to make sure everyone on your team starts reducing scope of their features and merging in smaller and smaller features sets.
There’s nothing inherit in the trunk based development model that stops someone from sitting on changes for a month, never pulling, and then trying to pull and ending up with a bunch of conflicts anyways. So it really feels like “yeah use trunk based development” boils down to “integrate continuously” which can be done with a branching model.
Exactly my reaction as well. The only ‘benefit’ she lists that I can truly see is ‘greater visibility into the code everyone else is working on’ but frankly that seems like it could be a burden as well.
Sometimes you don’t need to know. If your team organizes it’s projects and assignments well, you very well may be able to work on your small piece and integrate it without really needing to know every little thing every other person is working on.
With frequent commits branches just seem like an easier way to resolve conflicts as well as speed up the ability for others to test and merge their changes while you can resolve issues with a build.
You can also typically see team mates branches in repos… Seems they are just missing SVN?
And the whole thing with running CI builds on branches not being “integrating” until merge time is so funny to me.
Like, does this person not know that you can merge
master
back into a feature branch, such that you are, in fact, integrating the feature branch up to date with master? And it’s done… Gasp without breaking the master build for everyone else in the mean time!?!And the parts about pair programming and knowledge sharing are easy to fix, too. Just have regularly scheduled pairing sessions with the people who need to knowledge-share.
Trunk-based suggestions always comes across to me as “I don’t understand how to do feature branches/PR-based development”
TBD only says that you should have less branches than the other branching models. I quite like it and have used with git and merge requests. I may be misunderstanding something, but I only see this as a way to organize the branches, nothing more.
deleted by creator
deleted by creator
That’s not how I’ve ever understood folks to be describing TBD, but perhaps I’m misunderstanding it. To me it has always sounded like people should just commit to master and always commit tiny atomic commits.
And I work at a company who switched to “trunk-based development” but because of bureaucracy, nothing can be merged early. Big feature branches still sit waiting for months, then need a big document describing the changes and their impact, some QA team to test the new feature branch build etc. The “release management” team simply renamed the develop branch to trunk and called it trunk-based development.
I disagree with a lot of the premises presented. Not that I think trunk based itself is good/bad or anything, but some of the arguments don’t convince me.
(All emphasis is mine, I didn’t copy the author’s because I’m lazy and on mobile lol.)
1. Speed and Efficiency
[…] This is literally “Continuous Integration (CI)”, as originally suggested by the practices of Extreme Programming. While these days we tend to mean “run your build and tests on a team server every time you commit” when we say CI, what CI really meant was actually integrate your code regularly. Code living on separate branches is, by definition, not integrated. […]
I don’t disagree with anything here, I only quote it because arguments where each side is using different definitions are pointless. The author is using a different definition of CI than what most developers would use so I wanted to make sure it is mentioned.
2. Greater Code Stability
[…] we don’t want big merges from long-lived branches - the longer we leave it to commit our changes, the higher the chances our commit will clash with someone else’s changes. By frequently pulling in the other developers’ changes, and frequently pushing small changes of working code, we know the codebase is stable and working.
The author sort of seems to use a different version of the term codebase in the emphasis but that just seems to be an extension of their view on what CI means. I would say my codebase is stable if the main branch is stable. They maybe seem to include branching developers’ unmerged code as part of the codebase but I’m unsure.
Of course, this assumption of “stable and working” is easier to check if we have a CI server that’s running the build and tests for each of these commits. We also have to stop making commits if the build breaks at any time and focus on fixing that build. Continuously pushing small, frequent commits when the build is already broken isn’t going to do anyone any favours.
[…]
4. Improved Continuous Integration and Delivery (CI/CD) Practices
[…]
In a trunk-based model, continuous integration becomes more straightforward because your code is committed frequently to trunk, and that’s the branch your CI environment is running the build and tests on. Any failures there are seen and addressed promptly, reducing the risk of nasty failures. It’s usually easy to track down which changes caused the problem. If the issue can’t be fixed immediately, you can back the specific changes that caused it.
[…]
This is the part is disagree with the most. It is trivial nowadays to not allow a branch to merge unless a build passes and it is also trivial to have that be a build of the would-be merged code as opposed to the code on the branch. Now to be fair, I believe you could also do this with a trunk approach. You could have some hook which rejects commits, but that might be too slow. Instead you could do something like have a main and stable branch and push to main but pull from stable to deploy. Then have a process that checks each commit of main for the build passing and advances stable branch forward one commit.
In short, I disagree that in a branching environment it is difficult to keep the build passing. (I agree that CI is more difficult with their definition of CI though.) The build failing should never be a surprise with either approach (apart from crazy weird edge cases that would effect both approaches). If it is inconvenient (or impossible) to run the build locally that should be addressed and I believe the author would agree with me (mentioning tests they seem to encourage unit testing), but they’re seeming to say it is impossible so maybe they have a point I misunderstand.
Continuous delivery also thrives in a trunk-based development environment. Successful continuous delivery hinges on the ability to have a codebase that is always in a deployable state. The trunk-based development approach ensures this by promoting frequent commits, frequent integrations, and tests on all of these integrations. The small number of changes being introduced at any one time makes the software easier to deploy and test.
I see no reason why the trunk based approach encourages tests and the branch based approach discourages them. I see no reason why someone trying to ignore their responsibilities of writing tests is more likely to do it for big changes than small changes because they’re still making more small changes. So if they’re only writing like 50% of the tests they should I don’t see why it wouldn’t manifest as them skipping tests on half of their commits.
In contrast, implementing effective CI/CD can be more complex and time-consuming with the branching model. While it’s tempting to think “Well, I run my build and all my tests on my branch”, you’re not actually integrating every time you commit. It’s at merge (or rebase) time that you start to see any integration issues. All those tests you were running on your branch “in CI” were not testing any kind of integration at all.
Merging and testing code from different branches can introduce delays and potential errors, which takes away some of the benefits of having a build pipeline in the first place.
I spoke on this above, but it is easy to have your CI server build a potential merge rather than the branch itself.
Like I said at the start, I’m not saying anything about trunk based development as a whole, I just disagree with some of the arguments they claim make trunk based superior.
My understanding of trunk based development is that it allows for short lived branches and keeps longer work behind feature flags as it is merged in pieces. The common CI approach with pull/merge requests having to pass tests still applies.
That isn’t what the author describes, but I agree there are multiple interpretations.
For me, history documents changes and intention. Trunk based development seems inherently incompatible to that.
Many small commits intertwining different concerns makes it practically impossible to grasp changes by concerns or change sets. Once an issue inevitably occurs you may be able to work on the current state, but you can’t check what was changed together and why. If it’s not obvious from the code base you won’t be able to quickly assess the context.
The idea or thesis that many changes would lead to more stability (always deployable) is baffling to me. Changes are what introduces new issues. Mixing and intertwining concerns and people unaware of other changes in close time proximity increases risk.
More commits also don’t mean CI is more stable. A merge request as a gate to CI success is what does. A failed build on trunk already failed and blocks others.
While I develop a solution I specifically don’t want it on main. It’s a messy process, that may be partially reverted. Once I found my approach I clean up / define history and explain the approach and changes.
I want to commit the messy process too, for reference of my changes and approaches, and to have stuff I split off and integrate later. None of that belongs into main before I’m confident in the approach and changes. Because it’s specifically not stable and should not be deployed.
The recommendation to make small, focused changes and commit frequently are good practices for using git as well. Any changes a developer has locally are effectively a branch, so I don’t see much of a difference between the two approaches, at least in the context of this article.
Regarding section 1, won’t you still get the conflicts when pushing to remote (or pulling from it)?
Precisely. In practice, trunk based development just means your branch is local instead of on remote.
What do you mean by local? git can hide merges or feature branches, and you have to save your temporary code by pushing it to the server at the end of the day. You can rebase your code or squash it before merging, but TBD is not talking about that IIRC.
If the work I’m doing is on a feature branch on remote or locally, why does it matter to the rest of the team? My integration steps can be done on a server instead of locally. TBD forces teams to collaborate synchronously since changes are pushed straight to trunk. Rebase or squashes are irrelevant here.
Another poster put it great: TBD is trying to solve a culture problem. Feature branches and pull requests into main is much more flexible. The only time TBD make sense is for small teams - like 2 or maybe 3. And even at 2, I’d much rather create feature branches that merge into main.
TBD forces teams to collaborate synchronously since changes are pushed straight to trunk
The main page about TBD says you can still use feature branches, merge requests, or squash/rebase, and that’s how I use it. It only says why and how you should use release branches, and how you should fix bugs in a release. The linked article is not talking about TBD at all, hence my confusion about this whole post.
I’m actually confused by the whole post.
In contrast, the branching model
TBD is a branching model which works fine with DVCS. I’ve used it successfully with git and it was better than the other “git/github flows.”
The point of TBD is to have well-defined branches for certain tasks or topics. Nothing is forced for how you achieve this. For example you won’t get conflicts if you have a rule to merge the master/develop/main branch, or squash or rebase your commits on your feature branch before your merge request is ready.
Also, I disagree with the person who says it’s a “developer culture problem.” IMHO it’s a branching model that should be respected in the same way we have rules for code formatting or using linters before a commit whether it’s a tool, a hook, or a check in the CI.
Overall I prefer TBD because it has fewer branches than the other methods.
This type of workflow is natively supported by https://github.com/facebook/sapling, https://github.com/jiju-git and https://github.com/arxanas/git-branchless. Both these tools can interact with normal git repositories.
The idea is to divide commits between public commits that are untouchable and under-dev-commits that can be amended, split, merged, reorderdered, and so on. One can play freely with under-dev-commits, because every modification done on them is locally registered, and one can navigate in a tree of undo.