3 min read

How We Use Epic Branches. Without Breaking Our Flow.

TL;DR: Epic branches help us break large features into focused PRs without leaking unfinished work into our mainline code. They preserve review quality, support parallel development, and let us ship full features confidently - all without the rebasing chaos.


The Problem We Had

Large features often ended up as massive PRs. These were hard to review, difficult to reason about, and often led to delays or surface-level feedback. They also created pressure to rush merges or compromise on quality to get something over the line.

We wanted:

  • Clear, focused PRs where reviewers could understand the "how"
  • A way to group together everything a feature needed, without dumping WIP code into the mainline
  • A clear path from development to staging to release, without rebasing hell

What We Tried (And Why It Didn't Work)

Like many teams, we tried a few variations:

  • Long-lived feature branches with a single monster PR - worked okay for solo work, terrible for shared work or review speed
  • WIP commits behind feature flags - hard to test, noisy history, increased risk of unfinished features leaking

None of these gave us the combination of clean reviews, team collaboration, and confident shipping we wanted.


What We Do Now: Epic Branches

We now create epic branches for every large project, using the naming convention epic/feature-name - for example:

epic/new-checkout-flow
epic/improve-api-usage
epic/refactor-auth-pipeline

Then, every piece of that feature is implemented via small, focused PRs into the epic branch. We squash-merge each PR into the epic so that the commit history stays readable, but we do not squash the epic itself when it merges into our mainline branch. This lets us preserve the history of all the well-scoped changes that made up the feature.

One of the best parts? Epics can be based on other epics. This lets us start work on dependent features without waiting for the base feature to fully ship. It's been huge for parallel development without constant rebasing or artificial blockers.


What This Unlocks

  • Small, reviewable PRs with clear scope and purpose
  • A complete, testable version of the feature that's not in the mainline yet
  • Isolation from release branches while development continues
  • Easy full-feature testing in staging before promoting
  • Collaboration across devs - no more one-person bottlenecks
  • Safe merge into the mainline once everything is ready

It's not just about code structure - it's made our process feel calmer and more deliberate.


Trade-Offs and Things to Watch

  • You need to keep epics in sync with your mainline to avoid drift
  • The final epic PR still needs a review of the full diff
  • Naming discipline and merge rules need to be shared across the team
  • Working in epics requires more Git awareness than a simple feature-branch model

But those trade-offs have been more than worth it for us.


Would We Recommend It?

Absolutely - if you're building features that:

  • Span multiple concerns or developers
  • Require staging as a complete unit
  • Would be painful to integrate into your release stream piece-by-piece

This approach isn't necessary for every change, but it's ideal for features that carry more complexity, cross-team coordination, or delivery risk. Epic branches give you a structured way to manage that complexity while preserving flexibility and clarity.

Once your team gets used to the flow, it doesn’t feel like process overhead - it feels like momentum.