← Back to list

Why We Stopped Branching from Development: Our Production-First Git Workflow

Every Git branching strategy has one thing in common:

DevMan98 · 2026-07-14 09:17 · 0 claps · 3.8 min read
#devops #gitflow #workflow #agile-release-train #software-development
Open on Medium ↗
Wiki topics: ☁️ · DevOps & Cloud 📋 · Product Management

Why We Stopped Branching from Development: Our Production-First Git Workflow

Every Git branching strategy has one thing in common:

Developers are encouraged to branch from the development branch.

Whether it’s GitFlow, GitLab Flow or a simplified feature branching model, the assumption is almost always:

Development is the source of truth.

We decided to challenge that assumption.

Instead, we made Production our source of truth.

This article explains why.

The Problem with Branching from Development

Imagine your project looks like this:

Live
└── Production
Dev
├── Feature A
├── Feature B
├── Feature C

You need to build Feature D.

Traditionally you’d branch from Dev.

Immediately your branch contains:

  • Feature A
  • Feature B
  • Feature C
  • Your own work

Now imagine Feature B is incomplete.

Or Feature C has introduced a bug.

Or Feature A changes an API you’re relying on.

Suddenly you’re trying to determine whether a bug belongs to your feature or someone else’s.

Your branch is no longer:

“My feature”

It’s become:

“Everything that’s currently in development.”

That didn’t sit right with us.

Our Philosophy

We wanted one guarantee.

A feature branch should always represent Production + My Change.

Nothing more.

Nothing less.

If production is stable, then my branch should also be stable apart from the code I’m actively writing.

That single rule changes the entire branching strategy.

Our Workflow

Instead of branching from Development, every feature and hotfix branches from Live.

Live
├── Feature A
├── Feature B
└── Hotfix C

Each branch is isolated.

If I check out Feature A, I know exactly what I’m running:

Production
+
Feature A

Not Feature B.

Not Feature C.

Not half-finished work from another developer.

Just my changes.

What About QA?

We still have a Dev branch.

But it’s not where development happens.

It’s where validation happens.

The workflow looks like this:

1) Branch from Live.
2) Develop feature/hotfix.
3) PR into Dev.
4) Dev automatically deploys to the development environment.
5) QA tests and signs off.
6) Merge the same feature branch directly into Live.
7) Live deploys to production.

The important distinction is this:

Dev exists to validate releases — not to act as the parent branch for development.

Why This Works

Local testing becomes deterministic

When I run my feature locally I know I’m testing:

Production
+
My Feature

There are no unknown variables.

If something breaks, it’s probably my code.

QA tests integration

The Development environment has a different purpose.

It answers a different question.

Instead of asking:

Does my feature work?

It asks:

Does my feature work alongside everything else currently awaiting release?

That’s exactly what QA should be testing.

Merge conflicts become useful

One unexpected benefit is merge conflicts.

Most teams hate merge conflicts because they’re often caused by feature branches drifting away from Dev.

In our workflow, conflicts mean something.

They tell us:

Two developers genuinely modified the same code.

That’s valuable information.

We’re resolving real conflicts — not synchronising stale branches.

Production is always reproducible

Need to investigate a production bug?

Checkout Live.

Need to test your feature?

Checkout your feature branch.

Need to test upcoming releases?

Checkout Dev.

Each branch has a clear purpose.

What Happens if a Feature Isn’t Released?

Sometimes QA rejects a feature.

Sometimes priorities change.

Sometimes work is abandoned.

That’s fine.

The feature never reaches Live.

Eventually, once there are no outstanding releases or QA work in progress, we simply reset Dev back to Live.

Live
│
├── Released Features
│
└── Dev
      ▲
      │
 Reset to Live

Dev isn’t intended to accumulate months of history.

It’s a temporary validation branch.

Advantages

We’ve found several benefits.

  • Every feature is built against production.
  • Local testing is predictable.
  • Production bugs are easy to reproduce.
  • QA validates integration before release.
  • Feature branches stay clean.
  • Merge conflicts represent genuine conflicts.
  • No constant merging of Dev into feature branches.
  • Every feature is independently deployable.

Trade-offs

No workflow is perfect.

This approach has some considerations.

Features depending on other features

If Feature B depends on Feature A, both can’t simply branch from Live independently.

You may need to:

  • finish A first
  • branch B from A
  • or create a temporary integration branch

Fortunately, in our experience this is relatively uncommon and usually indicates that the work could be broken down differently.

Dev can become busy

If multiple features are in QA simultaneously, Dev represents:

Production
+
Feature A
+
Feature B
+
Feature C

That’s intentional.

It’s validating how upcoming releases work together.

However, we avoid merging unfinished work into Dev. Only code that’s ready for QA should be promoted.

Discipline matters

This workflow relies on process.

Developers shouldn’t:

  • develop directly on Dev
  • merge unfinished work into Dev
  • reset Dev while QA is active

The workflow is simple — but consistency is important.

Is This Better Than GitFlow?

Not necessarily.

GitFlow solves a different problem.

GitHub Flow solves a different problem.

Trunk-based development solves a different problem.

This workflow suits teams that:

  • maintain a stable production platform
  • release features independently
  • have a dedicated QA environment
  • want developers to work from the production baseline
  • value predictable local testing

If you’re deploying continuously dozens of times per day with heavy feature flag usage, trunk-based development may be a better fit.

If you’re managing multiple supported release versions, GitFlow may fit better.

There isn’t a universal “best” branching strategy — only one that aligns with your team’s needs.

Final Thoughts

We didn’t invent a new version of Git.

We simply asked one question:

Why are we branching from code that hasn’t been released yet?

For us, the answer was to stop doing that.

Production became the source of truth.

Development became validation.

Feature branches became exactly what they should be:

Production + My Change.

It’s a small change in philosophy, but it has had a noticeable impact on how we develop, test, and release software.

I’d be interested to hear how other teams approach this. If your workflow differs, or if you’ve encountered similar challenges, let me know in the comments. The best engineering practices often come from comparing real-world experiences rather than following convention.


메타데이터
post_id
b486c40f0c1b
slug
why-we-stopped-branching-from-development-our-production-first-git-workflow-b486c40f0c1b
url
https://medium.com/@DevMan98/why-we-stopped-branching-from-development-our-production-first-git-workflow-b486c40f0c1b
canonical_url
https://medium.com/@DevMan98/why-we-stopped-branching-from-development-our-production-first-git-workflow-b486c40f0c1b
author_url
https://medium.com/@DevMan98
status
ok
fetched_at
2026-07-31 01:28:13