Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

Git Collaboration Playbook

License: MIT Web Reactions

Practical guide to branching strategies, pull request flow, stacked PRs, merge queues, and CI collaboration in large teams.

If I were setting up how a large team ships through git today, what would I standardize before the first hundred PRs land?

This playbook focuses on:

  • branching models and when each earns its place;
  • branch protection and required checks;
  • PR flow that scales past a handful of engineers;
  • stacked PRs and how to land them;
  • merge queues and why "green on branch" lies;
  • rebase vs merge policy;
  • conflict habits and CI collaboration;
  • release branches and backports.

Table of Contents


Companion playbooks

These repositories form one playbook suite:


Philosophy

The best git workflow is not the cleverest one.

It is the one where:

  • any engineer can describe the path from branch to production in one sentence;
  • the default branch is always releasable;
  • merging is boring, frequent, and automated;
  • history reads as a sequence of reviewed, revertable units;
  • nobody needs tribal knowledge to land a change.

The goal is not process. The goal is removing coordination as a daily tax.

Scope boundaries: how reviews are written and received lives in the Code Review Playbook; commit message format is its own topic (Conventional Commits); CI pipeline design and rollout safety live in the DevOps Delivery Playbook. This playbook is about how branches, PRs, and merges flow between people.


The defaults I'd reach for first

If I were setting up a team repository today, I would usually start with:

  • Branching: trunk-based-ish — short-lived branches off the default branch, merged within days
  • Merge method: squash merge for PRs, one commit per reviewed unit
  • Protection: branch protection on the default branch from day one, admins included
  • Merge queue: enabled once the team is large enough that PRs race each other
  • Hygiene: auto-delete merged branches
  • Auto-merge: on, so approved PRs land the moment checks pass
  • History: linear, no merge commits on the default branch

Branching models

Three models cover almost every team:

  • Trunk-based development — everyone integrates into the default branch continuously, branches live hours to days, incomplete work hides behind feature flags
  • GitHub Flow — branch, PR, review, merge, deploy; the default branch is always deployable
  • Release branches — a stabilization branch cut per release, fixes cherry-picked back

In practice trunk-based and GitHub Flow converge: short-lived branches, PR review, fast merges. The real spectrum is branch lifetime, not model name.

When each earns its place

  • trunk-based: continuous deployment, strong CI, feature flags available
  • GitHub Flow: the sensible default for web services and libraries
  • release branches: versioned products, multiple supported versions, external release cadence you do not control

Smells

  • a branch older than a week that is still "almost ready"
  • a develop branch that exists because it always has
  • integration branches that need their own integration branches
  • merge day as a named event on the team calendar

A long-lived feature branch is a batch of unreviewed risk with a merge conflict attached. Break the work down instead — see Splitting large changes.


Branch protection and required checks

Protection rules are the contract that keeps the default branch releasable. My baseline:

  1. Required status checks. The checks that gate merging are the definition of "safe to ship". Choose them deliberately.
  2. Required reviews scaled by risk. One approval as default; two for auth, payments, migrations, and other blast-radius code — enforced via CODEOWNERS, not memory.
  3. Linear history required. Squash or rebase merges only; no merge commits on the default branch.
  4. Admins are not exempt. The moment admins can bypass, the rules are decorative. Emergencies go through the same gate, faster — not around it.
  5. Force pushes and deletions blocked on the default branch.

Which checks should be required is a CI design question — covered in the DevOps Delivery Playbook. The collaboration rule is simpler: required checks are few, fast, and trusted; everything else is advisory.


PR flow at scale

Small PRs are the single highest-leverage habit in this playbook.

  • one coherent change per PR — reviewable in one sitting;
  • a few hundred lines of meaningful diff as the soft ceiling;
  • draft PRs for work-in-progress that wants early eyes without requesting review;
  • the PR description states what changed and why, not a diff narration;
  • open-to-merge time measured in hours or days, never weeks.

A PR that is hard to review gets a worse review. Review quality itself is the Code Review Playbook's territory.

Splitting large changes

  • separate mechanical changes (renames, formatting, codemods) from behavioral ones
  • land the refactor that enables the feature before the feature
  • ship the schema or contract change ahead of the code that uses it
  • if a split creates a dependency chain, that is a stack — see Stacked PRs

Keeping branches fresh

  • update from the default branch when meaningfully behind, not on every push;
  • a merge queue makes ritual pre-merge updates unnecessary — the queue tests against latest anyway;
  • a branch that needs constant conflict resolution is telling you it has lived too long.

Stacked PRs

When stacking beats one big PR

A stack is a chain of dependent PRs, each reviewable alone: PR 2 branches from PR 1, PR 3 from PR 2. Reach for it when:

  • the change has natural layers (schema → API → UI)
  • you would otherwise ship one 2,000-line PR
  • you want to keep building while earlier parts sit in review

The alternative to a stack is usually a giant PR that gets a worse review, or a week of blocked waiting.

Tooling

Tool Good when Watch out for
Graphite team-wide adoption, wants a full stacking workflow a paid product; the team depends on it
git-spice CLI-first, free, no server component newer; smaller ecosystem
plain gh + branches occasional stacks, no new tooling manual restacking after every change below the top

The mechanics are the same everywhere: each PR targets the branch below it; editing a lower branch means rebasing everything above. Tooling automates the restack; by hand it is painful past two levels.

Landing a stack

  • review bottom-up: the base PR first, since everything above depends on it;
  • land bottom-up: merge PR 1, retarget PR 2 to the default branch, repeat;
  • keep each PR independently green — a stack where only the top passes CI is one big PR wearing a costume;
  • never merge the top of a stack ahead of its base.

Merge queues

Why "green on branch" lies

A PR's checks run against the default branch as it was when the checks started. Two PRs can each be green, conflict-free, and still break the build when both land — a renamed function in one, a new caller in the other. Git sees no conflict; the compiler does.

At low merge frequency this is a rare annoyance. At high merge frequency it is a broken default branch several times a week, and every break blocks the whole team.

A merge queue fixes it structurally: PRs enter a queue, and CI runs against the actual future state of the branch — this PR plus everything queued ahead of it. GitHub's merge queue builds these speculative states in parallel, merges what passes in order, and ejects failures instead of landing them.

  • the queue's answer is authoritative — no bypassing it because a PR "looks safe";
  • queue throughput depends on check runtime — see check runtime budgets;
  • a kicked-out PR is the system working.

When a small team does not need one

A handful of engineers merging a few PRs a day rarely race each other. There, required checks plus auto-merge give the same safety with less machinery. The signal to adopt a queue is empirical: the default branch breaks from PR interleaving more than about once a month. Before that, a queue is ceremony.


Rebase vs merge policy

My policy fits in four lines:

  • squash merge is the default for landing PRs — one reviewed unit becomes one commit, revertable with git revert;
  • rebase locally to update your own unshared branch — clean, linear, no merge-commit noise;
  • never rewrite shared history — once a branch has a second person's work or a merged state, its history is fixed;
  • merge commits are for the rare deliberate case (importing a subtree, preserving a collaborative branch), not the default.

Force-pushing your own PR branch is fine — it is your branch until it merges. Use --force-with-lease so you cannot clobber a push you have not seen.


Conflict habits

Conflicts are not random weather. They are proportional to diff size times branch lifetime.

  • small PRs and short-lived branches prevent most conflicts before they exist;
  • rebase early — a conflict caught on day one is a two-minute fix, the same conflict on day ten is an afternoon;
  • resolve conflicts on your branch, never on the default branch;
  • lockfiles (pnpm-lock.yaml, package-lock.json) are generated files: never hand-merge them — take either side, then re-run the install to regenerate;
  • the same file conflicting week after week is a boundary problem — covered in the Software Design Playbook.

CI collaboration

CI is a shared resource and a shared contract. What I want:

  • Required checks are the merge gate: few, fast, deterministic. Everything slow or advisory (nightly suites, coverage deltas, preview deploys) runs as optional and never blocks.
  • Auto-merge on, so a PR lands the moment approval and checks align — nobody babysits a green PR waiting to press a button.
  • Check runtime budgets: required checks in about ten minutes, hard ceiling fifteen. Past that, engineers batch changes into bigger PRs, and every rule in this playbook degrades.
  • Failures on the default branch are the team's top priority — a red trunk blocks everyone.

Pipeline architecture — caching, parallelization, what runs where — is the DevOps Delivery Playbook's domain. Which tests exist at which layer is the Testing Strategy Playbook's.

Flaky checks

A flaky required check is worse than no check: it trains the team to distrust red.

  • quarantine known-flaky tests out of the required set immediately, with a tracking issue and an owner;
  • never build a "re-run until green" culture — every ignored red makes the next real failure invisible;
  • a re-run that flips the result is a defect report, not a fix;
  • a required check that fails spuriously more than about 1% of runs loses its required status until repaired.

Release branches and backports

Most continuously deployed services do not need release branches. The default branch is the release.

They earn their place when:

  • you ship versioned artifacts (SDKs, CLIs, mobile apps, on-prem software)
  • multiple versions need support in parallel
  • an external release calendar forces a stabilization window

Cherry-pick discipline when you have them:

  1. Fix on the default branch first, then cherry-pick to release branches — never the reverse, or the fix silently misses the next release.
  2. Cherry-pick the merged squash commit with git cherry-pick -x so the backport records its origin.
  3. Backports get PRs and required checks like any other change — a release branch is the least safe place for an unreviewed commit.
  4. Delete release branches when their version leaves support.

Things to avoid

  • long-lived feature branches as the standard unit of work;
  • admins bypassing branch protection "just this once";
  • 2,000-line PRs reviewed by scrolling speed;
  • force-pushing shared branches;
  • re-running flaky checks until green and calling it passing;
  • required checks slow enough that people batch changes to avoid them;
  • merge queues on a three-person team as cargo cult;
  • treating the branching model as identity instead of a tool that must earn its cost.

Worth reading


License

MIT is a sensible default for a repository like this, but choose the license that fits how you want others to reuse the material.

About

Practical guide to branching strategies, pull request flow, stacked PRs, merge queues, and CI collaboration in large teams.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors