---
# System prepended metadata

title: '#22.9 TBD 讀網站會 - Short-Lived Feature Branches'
tags: [Meetups]

---

---
title: "#22.9 TBD 讀網站會 - Short-Lived Feature Branches"
tags: Meetups
date: 2022-07-28
---

https://trunkbaseddevelopment.com/committing-straight-to-the-trunk/
https://trunkbaseddevelopment.com/short-lived-feature-branches/

## Committing straight to the trunk

Some teams will choose to commit/push straight to the trunk. Most likely it is because they are a small team with each team member knowing what the others are up to. Their build is probably fast and relatively exhaustive, and they may well seldom experience a build breakage. If the build does break (post integration into trunk/master) then they most likely ‘revert’ the commit straight away, possibly locking the trunk for a short period of time while that is performed. If the team is really small (say three or four), in which case the team might allow someone to fix the build quickly and commit that in order to get the build green again.

In the 2000’s many Trunk-Based Development teams might have numbered up to 100 committers. They may have been extremely rapid with their reverts (lock trunk, revert, kick off the CI daemon again, unlock trunk if green again). If there was no build-automation server, they would have performed check-in activities that 1997’s C3 team would have recognized, because they wanted that human assurance that gated check-ins are all that is needed to **keep the build green**. 
Namely, developers holding an “I/we are checking in now, nobody else should be”. They run the full build after bringing their checkout up to date and commit/push if green. 

Indeed that ceremony is a key part of the Continuous Integration advances and is now part of Agile generally, and Extreme Programming in particular. 
These days teams doing this practice are likely to be much smaller (say less than 16) because of the advent of alternatives (see below). 
That said, there are still some large teams working this way.

## Benefits

It is easier to **objectively verity** the correctness of your commits yourself (optimally with a pair-programming partner), then commit/push at moments of convenience. 

That is, easier than pushing into a code-review system for approval from a teammates that risks being interruptive to their workflow.

Indeed there is a greater likelihood that this this style or working becomes a flow of small commits into the trunk, with each of those being an incremental step forward, and perfectly able to go-live itself while the larger story/card remains incomplete.

## Challenges

Committing (and pushing) straight to the trunk has a challenge. 
Principally, someone could commit/push code that breaks the build, 
and the server(s) setup to guard Continuous Integration don’t catch that for some time after the commit is available for teammates to pull/sync to their dev-workstation for unrelated work.

Risk mitigation is everyone running the full build (the same build the CI demon would do) before the commit/push, and only pushing to trunk if that passes. 
This is an essential integration activity. 
This is the habit of the XP teams from the end of the 90’s, and there’s no reason any team would dispense with that in the years since. 
Indeed, it is valuable for ALL branching models.

If this is locked in as a team requirement, your new challenge is **to keep the full build fast**. 
Fast is say one minute, and slow is ten or above. 
Compile and **pure unit tests** (no threads, sockets, file IO) is where good builds focus their development effort. 
Any following “integration test” build steps that use threads, listen on sockets, or do significant file IO should be minimized as far as possible without reducing meaningful coverage. 
The best trick for that is changing some integration tests into pure unit tests, which isn’t always easy.

Some teams have revert policies for commits that land in trunk/master that are proven as “broken” later in CI.
That could be an activity for a build-cop who’s going to communicate with the dev team about locking the trunk to achieve that. 
Or it could be a bot activity and happen instantly, as Google do in-house (35K committers in one trunk).

Some teams have some scripting in place to ensure that developers only pull/sync commits to their dev-workstations that CI has marked as passing. 
That could be as simple as keeping a commit ID (number or hash depending on your VCS tool) on a website somewhere, and writing a wrapper script for git-pull (or svn up) that ignores commits that happened after that one. 
Pushing back, with that way of working is harder in Git and Mercurial as they requires you to have pulled HEAD revision before you can push back. Subversion and Perforce don’t have that limitation.

## Alternatives to committing straight to the trunk
That modern alternative that allows development teams to scale up without having a bottleneck around check-ins or increased risk of broken builds: Short-Lived Feature Branches.

There are also teams that send patches to review systems like [Gerrit](https://www.gerritcodereview.com/) and Rietveld, instead of committing/pushing straight to trunk/master. 
Google pioneered this with their in-house Mondrian system in 2006, and Gerrit and Rietveld were made in the image of that. Facebook’s Phabricator is another that came later. As well as code review, build-automation systems objectively verify the correctness of the proposed changes, leaving you with high confidence that the following merge/integration into trunk/master will yield a similar positive result when the same infrastructure kicks in later for CI purposes. It is important to note that the automation you attach to commits/pushes to non-trunk branches (or patch queue/review systems) is not Continuous Integration itself.

These two alternatives, as well as committing straight to the trunk are compared in [Styles and Trade-offs](https://trunkbaseddevelopment.com/styles/).

---

## Short-Lived Feature Branches

This branching model was facilitated with the advent of very lightweight branching that came with Git and Mercurial in the mid-2000’s, though there is evidence that Google were effectively doing the same in their Monorepo for some years before.

Either as branching directly off master, or in a fork of the whole repository. These branches are destined to come back as “pull requests” into the master/trunk.

With the Pull Request (and code review) advance, the cut-off point for team sizes that graduated from “direct to the trunk” to short lived feature branches moved lower. While it was up to 100 before Git’s lightweight branching, it is now up to 15 people. With 16 or more, the team is more productive with short-lived feature branches, and corresponding CI daemons verifying those in advance of commits landing in the trunk.

One key rule is the length of life of the branch before it gets merged and deleted. Simply put, the branch should only last a couple of days. Any longer than two days, and there is a risk of the branch becoming a long-lived feature branch (the antithesis of trunk-based development).

Another key rule is how many developers are allowed congregate on a short-lived feature branch. Another simple answer: the developer count should stay at one (or two if pair-programming). These short-lived feature branches are not shared within a team for general development activity. They may be shared for the purposes of code review, but that is entirely different to writing production code and tests.



Sometimes the community calls these ‘task’ or ‘topic’ branches, instead of long-lived feature branch.

## Merge directionality

Short-lived feature branches are real branches and merge is a first class concept. In the run up to completing work on the short-lived feature branch, you will need to bring it up to date with master (trunk). That is an effective merge whichever way you do it. Look at the branch at this moment, it may appear to be much younger than it was before that operation. The changes have to now go back to master (trunk) in another merge operation. In GitHub, for ‘pull requests’ (or equivalent in other platforms), the user interface may handle that last merged back for you, and even go as far as to delete the short-lived feature branch.

To recap: merges to the short-lived feature branch are allowed to bring it closer to HEAD of master (trunk). Merges to master (trunk) are allowed only as part of closing out the short-lived feature branch (and just before deleting it).

## Two developers concurrently doing short-lived feature branches

Say two features are being worked on concurrently: features X and Y. Both will take a day to complete, and two developers are working independently on them. Or four developers if pair-programming is that team’s way. The reality of the merge back to master/trunk, before the deletion of the short-lived feature branch, is that the a merge of changes from master/trunk is often needed, before the merge to master/trunk.



Workflows include:

Attempt to merge to master/trunk and if that’s blocked do a merge/pull from master/trunk before attempting the push again.
Do a speculative merge/pull from master/trunk before attempting any push to master/trunk.
The latter leaves no trace if there’s nothing to merge in from the other branch.

## Workstations included

Really though Developers work on their own workstations. That is both for their “working copy” as well as their local Git clones complete with branches:

The white dots are just general development work (save files from the IDE), and the green dot is the same but validated by a local build that passes and a maybe a local commit.

While each developer works, they maintain a local clone of the master/trunk and their own short-lived feature branch only. Indeed for a period of time, their short-lived feature branch may not yet exist in the shared origin repo.

## Personal preferences

At some point, the short-lived feature branch has to be brought right up to date with master (trunk) in a merge operation before the result being merged back to trunk (and the branch deleted). There are a number of approaches for this, and while teams may have a policy, some teams leave it to personal preference for the developer.

## Git stash

Some people do git stash before git pull before git stash pop. There’s a chance that when you pop your working copy may be in a merge clash situation that has to be resolved before you progress. This way will always result in your change being a single commit, at the HEAD of the branch (as Subversion would always do).

## Git rebase

Some people do git rebase. Refer to a well written Atlassian document on this  as well as one from ThoughtBot  that talks about squash too. Even with this model, you may encounter a merge clash, and have to resolve that locally before you can push the result anywhere, or do further merges (to master hopefully).

## Pitfalls

Working towards a pull request can sometimes make you look past the power of streaming a series of small commits into trunk for the benefit of all. High-throughput XP teams from the end of the 90’s onward would stream tens of commits a day (per pair) into the trunk. Each commit would be an incremental step forward and able to go live as is, were the team to change plans to do so. A mistake in thinking for this way of working, is one pull-request for one Agile story/card (and no more). Getting out of that mind trap would be to practice (say) a pull-request for refactoring and see that integrated/merged into the trunk, then a pull-request for a piece of new functionality (and integrated into trunk), then perhaps another refactoring (trunk integrated again). And for those three pull-requests they shared the same Story/card association, but perhaps had different short-lived branch names - each of which was deleted after merge/integration.

## Breaking the contract

If you merged the part-complete short-lived feature branches to anywhere else, then you have broken the contract of trunk-based development. For short-lived feature branches, these are not allowed:

intermediate merges to master (trunk) - at least where the commit was not able to go live on its own
merges (intermediate or not) to other people’s short-lived feature branches
merges (intermediate or not) to any release branches (if you have them)
variations of #2 that are direct from/to the developers clone on their workstation
other developers joining you on your short-lived feature branches - at least who are not your pair-programming partner.
Alternatives to short-lived feature branches#
There is a more traditional alternative for smaller teams: Committing straight to the trunk. Many people still prefer this way of working, and if the whole team can do it without blowing up the build server, then great job team.

There is also the patch-review way of working that was outlined in Google’s use of Mondrian (2006), and consequentially delivered for non-Google teams with open source tools Gerrit and Rietveld (2007/8).

These two alternatives, as well as short-lived feature branches are compared in Styles and Trade-offs.
