Liam Asman's Blog

Trunk-based development

essay

-

What is trunk-based development?

Trunk-based development is a collaborative development approach where all developers commit directly to the main branch (often called “trunk”). Feature branches and pull-requests should be avoided. Instead, teams rely on fast feedback loops, high collaboration, and strong CI practices to maintain code quality and stability.

Why is trunk-based development better than branches?

Feature branches are ineffective for several reasons:

1. Slow feedback loop

The pull request cycle requires waiting for a reviewer. After receiving feedback, you make changes, then wait again. Repeat ad nauseum.

2. Merge conflicts

You wrote the code against a version of the main branch. It may have moved on since then. You now have to spend time fixing merge-conflicts.

3. Quality

Reviewers did not write the code. Reading and understanding code takes time, especially for a pull request for a full feature - otherwise it gets skimmed and rubber-stamped. Either quality suffers, or velocity does.

How do we keep quality high without pull requests?

Pair programming

Pair programming means continuous code review. No waiting. Code quality improves, defects are caught early, and features are developed faster as pairs bounce ideas between themselves, rather than waiting for responses to questions in a team channel.

Pair programming also results in better knowledge sharing and improved developer satisfaction.

Test driven development and responsive CI

Commit early, commit often. Comprehensive test suites should be run for every commit. The test suite should complete quickly - ideally within 10 minutes. If a commit breaks the build, revert immediately. Don’t wait for the next developer to notice. Don’t leave the broken commit while you fix the bug. Revert - push - fix - push.

Trunk should always be releasable.

Feature toggles and incremental commits

Big features often require a lot of work to get working; an acceptance test for a feature may not pass until the end of development. Instead of completing the entire feature before committing, disable the test and commit in small, testable increments.

Use static feature flags to disable compilation or run-time behaviour that shouldn’t be visible to users yet. You can safely commit code with a failing test, as long as it doesn’t cause the tests for existing behaviour to fail, and the failing test is disabled until the feature flag is enabled.

This lets us commit in small, frequent batches. Any merge conflicts will then hopefully be minimal in scope and impact.

Other benefits

Ship more often

The only code that matters is code that is in production. The only code that is in production is code that is in the main branch. Working on trunk means working on what matters.

By having trunk always in a releasable state, we can ship to production at any time. This means we can ship as often as we’d like.

Boosted morale

Developers like to get things into production. Having code sit on a feature branch for a long time damages morale. Big-bang releases are also anxiety inducing. Both of these are avoided with trunk-based development and frequent releases.

Better collaboration

Long-lived branches create knowledge silos; when a developer spends a long time on a feature branch they become the de facto owner of that code. If they are away for any reason, progress stalls.

This is avoided with pair-programming and frequent commits to the main branch which form a log of work done and break the task up into smaller, more manageable tasks.

In summary

For faster delivery, better software quality, and happier teams:

#technology #coding #programming #software development #rapid development #trunk-based development #branches #pull-requests #pair programming #test-driven development #tdd