Engineer's toolkit
Team workflows
Trunk-based development versus GitFlow, why small PRs and stacked diffs speed up review, and how monorepos and polyrepos trade tooling cost against coordination cost.
Git gives a team the same tools however it is organized. How the team uses those tools decides how often they merge, how big each review is, and how many repositories they have to coordinate. This page covers the workflow choices you will meet at work.
Concept
Before you start: a trunk is the main branch, main, that everyone integrates into. A feature flag is a switch in code that turns an unfinished feature on or off without a separate branch.
Trunk-based development vs GitFlow
GitFlow (Vincent Driessen, 2010) uses long-lived develop and main branches, plus feature, release and hotfix branches. It fits software shipped as versioned releases, such as desktop apps, on-premise products and libraries with several supported versions. Its author added a note in 2020 that it is not the right default for continuously delivered web software.
Trunk-based development has everyone integrate into main at least daily, through short-lived branches that live for hours to a couple of days. Unfinished features hide behind feature flags rather than living on branches, so main is always releasable. The DORA research behind Accelerate found trunk-based development among the practices linked with high delivery performance. Most product companies work this way, with CI running on every pull request and every merge.
Small PRs and stacked diffs
PR size is one of the strongest levers on review quality and speed. A 50-line change gets a careful review in minutes. A 2,000-line change gets "LGTM", and bugs hide in it (see code review). Aim for PRs that do one thing and can be reviewed in under 15 minutes. In practice that means under about 200 to 400 changed lines.
When a feature really needs 1,500 lines, split it into a stack. PR 1 adds the schema migration. PR 2, based on PR 1's branch, adds the data access layer. PR 3 adds the API endpoint, and PR 4 adds the UI. Each one is reviewed on its own, and you keep building on top while earlier PRs are still in review.
Stacked diffs came from Phabricator at Facebook, and tools such as Graphite, ghstack and Sapling support them. Plain Git has helped since version 2.38: git rebase --update-refs moves every branch in the stack when you rebase the bottom one.
Monorepo vs polyrepo
A monorepo keeps many projects in one repository. A polyrepo gives each service or library its own.
| Monorepo | Polyrepo | |
|---|---|---|
| Cross-project change | One atomic commit and PR | Coordinated PRs and version bumps across repos |
| Dependency versions | One version of everything, enforced | Each repo drifts on its own schedule |
| Code discovery and refactoring | Grep everything; large refactors are feasible | Harder to find usages |
| Tooling cost | Needs build tools that only build and test what changed (Bazel, Nx, Turborepo, Pants) | Standard tooling works out of the box |
| Scale limits | Git slows down at very large sizes without help | Each repo stays small |
| Access control | Coarse; per-directory ownership via CODEOWNERS | Natural per-repo permissions |
Google keeps most of its code, billions of lines, in one repository on a custom system called Piper. Microsoft moved Windows, around 300 GB, to Git, and built VFS for Git and later Scalar to make it workable. Much of that work, such as partial clone (git clone --filter=blob:none), sparse checkout and the commit-graph file, is now part of mainstream Git.
For a company with tens to hundreds of engineers, a monorepo with good CI caching is usually a productivity win. The deciding question is whether you will invest in build tooling that builds only what changed.
Common mistakes
- Letting branches live for weeks. Merge conflicts grow with the age of the branch. Integrate at least daily.
- Shipping an unfinished feature to
mainwithout a flag. Use a flag, so the code can merge without being on. - Stacking PRs without rebasing the stack. The top branches go stale. Use
--update-refsto move the whole stack together.
Check yourself
- Why does a 50-line PR usually get a better review than a 2,000-line PR? Reviewers can read and test a small change carefully. A large one tends to get a quick approval.
- What does a feature flag let a trunk-based team do? Merge unfinished code to
mainsafely, and turn it on when it is ready.
Key takeaways
- Trunk-based development, with short-lived branches and feature flags, suits continuously delivered web products. GitFlow suits versioned releases.
- Small PRs, or stacks of small PRs, are reviewed faster and more carefully.
- A monorepo makes cross-project changes atomic, but it needs build tooling to stay fast.
- Choose the workflow and repository layout by how your team ships, not by habit.
Further learning
Trunk Based Development describes the practice in detail, including feature flags and release branches.
Revisit merge, rebase and squash for the commands behind stacks and squash merges.
Related
Continuous integration and the software supply chain
Fast, trustworthy pipelines - build, test, artifact, scan and sign - plus DORA metrics and supply-chain controls that keep trunk green.
Code review
Author small, reviewable PRs and give reviews that improve both the code and the author — design first, tone that teaches, turnaround that unblocks.
Merge, rebase and squash
The three ways to combine a branch into main, what each one does to the commit graph, how to resolve conflicts without guessing, and the one rule about rewriting shared history.