Why Your Git Workflow Is Slowing Your Team Down

by Eric Hanson, Backend Developer at Clean Systems Consulting

The Workflow That Made Sense at Three People

Your team started with two developers who reviewed each other's code in five minutes, merged directly to main, and deployed the same afternoon. Then the team grew. You added a branch naming convention, a PR template, required approvals. Now PRs sit for two days waiting for reviews. Developers stack three features on top of each other because waiting for the last PR to merge is too slow. The integration branch is perpetually broken.

The workflow didn't scale because it was never designed — it accreted. Each rule was added in response to a specific incident, not as part of a coherent system.

The Bottlenecks, Named

PR queue depth is the most common problem. Work items are developed independently and submitted for review, but reviewers have their own work. If the average review turnaround is one day and each feature has two review cycles, each PR takes two to four days before merge. With four developers each submitting two PRs a week, the queue grows faster than it's consumed. The fix is not "review faster" — it's reducing PR size and cycle count.

Long-lived branches are the compounding version of the same problem. A branch that lives for three weeks accumulates merge conflicts with main as other work merges in. The developer has to spend time rebasing or resolving conflicts that wouldn't have existed if the work was integrated incrementally. The longer the branch lives, the worse this gets — a nonlinear relationship.

Review blocking on unrelated concerns happens when reviewers use the same approval mechanism for style nitpicks and architectural concerns. A comment like "this variable name isn't great" blocks the same way as "this approach will break under concurrency." Separating blocking vs. non-blocking feedback (GitHub Suggestions, the convention of marking nitpicks as nit:) prevents minor style preferences from gating a merge.

Integration hell from multiple feature branches happens when two branches both modify the same area of the codebase and neither knows about the other until merge time. You get conflicts that require understanding both changes to resolve correctly. With trunk-based development — where developers merge to main at least daily via short-lived branches or feature flags — this class of problem is nearly eliminated.

Diagnosing Your Workflow

Before changing anything, measure what's actually slow. The metrics that matter:

# Average time from PR creation to merge (needs your Git host's API or CLI)
# GitHub CLI example:
gh pr list --state merged --limit 100 --json createdAt,mergedAt \
  | jq '[.[] | ((.mergedAt | fromdate) - (.createdAt | fromdate)) / 86400] | add / length'
# Output: average days to merge

# PRs merged per week
gh pr list --state merged --limit 100 --json mergedAt \
  | jq 'group_by(.mergedAt | split("T")[0] | split("-")[0:2]) | map(length)'

If average merge time is over two days, you have a review throughput problem. If it's under a day but deploys are slow, the bottleneck is downstream in CI or deployment. These require different fixes.

What Actually Makes Git Workflows Faster

Smaller PRs. The research on code review (Cisco's study on code review, SmartBear's data on defect density) consistently shows that reviewers become less effective above 400 lines of diff and review velocity drops sharply above 200. Keep PRs under 300 lines of diff wherever possible. If a feature is large, break it into stages: data model first, then service layer, then API, then UI integration.

Draft PRs for early feedback. Opening a draft PR when you start a feature, not when you finish it, gets asynchronous architectural input before you've built on a foundation your reviewer disagrees with. It also reduces the "waiting for review" phase because reviewers have context from seeing the work develop.

Merge queues for CI efficiency. GitHub's merge queue (available on Team and Enterprise plans) and GitLab's merge trains batch PRs and run CI against the combined result, preventing situations where two PRs each pass CI individually but break when merged together. For teams with CI times over ten minutes, this is a meaningful throughput improvement.

Code ownership with CODEOWNERS. Automatically assigning reviewers based on file paths removes the latency of manually pinging people:

# .github/CODEOWNERS
/src/payment/    @payments-team
/src/auth/       @security-team
/infra/          @platform-team
*                @tech-leads

This ensures the right people are notified immediately when relevant code is changed, rather than the PR sitting in a generic queue.

Stacked PRs for dependent work. When you need to start work that depends on an unmerged PR, stack the branches:

git checkout feature/data-model
# work on data model PR

git checkout -b feature/service-layer
# base service layer on data-model branch
# when data-model merges, rebase service-layer onto main

Tools like gh stack or the Graphite CLI manage stacked PR chains with rebasing automation. The tradeoff: rebasing is required when the base branch changes, which adds friction. Worth it for features where waiting would block for days.

The One Change That Has the Highest ROI

If your team is stuck in slow review cycles and you can only change one thing: reduce your PR size. The research, the anecdotal evidence, and your own experience all point to the same conclusion. A 150-line PR with clear context gets reviewed in twenty minutes. A 1,500-line PR sits for two days and gets a cursory approval because nobody has time to actually read it.

Break features into smaller vertical slices. Merge behind feature flags. Split refactors from behavior changes. You'll ship more often, get better feedback, and have fewer integration problems. The workflow constraint should be maximizing merge frequency, not minimizing branch count.

Scale Your Backend - Need an Experienced Backend Developer?

We provide backend engineers who join your team as contractors to help build, improve, and scale your backend systems.

We focus on clean backend design, clear documentation, and systems that remain reliable as products grow. Our goal is to strengthen your team and deliver backend systems that are easy to operate and maintain.

We work from our own development environments and support teams across US, EU, and APAC timezones. Our workflow emphasizes documentation and asynchronous collaboration to keep development efficient and focused.

  • Production Backend Experience. Experience building and maintaining backend systems, APIs, and databases used in production.
  • Scalable Architecture. Design backend systems that stay reliable as your product and traffic grow.
  • Contractor Friendly. Flexible engagement for short projects, long-term support, or extra help during releases.
  • Focus on Backend Reliability. Improve API performance, database stability, and overall backend reliability.
  • Documentation-Driven Development. Development guided by clear documentation so teams stay aligned and work efficiently.
  • Domain-Driven Design. Design backend systems around real business processes and product needs.

Tell us about your project

Our offices

  • Copenhagen
    1 Carlsberg Gate
    1260, København, Denmark
  • Magelang
    12 Jalan Bligo
    56485, Magelang, Indonesia

More articles

Spring Boot API Documentation With OpenAPI — Generating, Hosting, and Keeping It Accurate

API documentation that drifts from the implementation is worse than no documentation — it misleads integrators and wastes time. Here is how to generate accurate OpenAPI specs from Spring Boot code, keep them in sync, and host them effectively.

Read more

TDD Does Not Mean Writing Tests for Everything. Here Is What It Actually Means.

A common misreading of TDD treats it as a rule requiring a test before every line of code. The actual practice is more selective and more practical — applied where it provides design leverage, skipped where it does not.

Read more

JPA Query Optimization — What Hibernate Generates and How to Control It

Hibernate generates SQL from your entity model and query methods. The generated SQL is often correct but rarely optimal. Understanding what gets generated — and the specific patterns that override it — determines whether JPA is a productivity tool or a performance liability.

Read more

The Hidden Cost of Cheap Developers

“We found someone way cheaper — let’s go with them.” That decision often feels smart… right up until it isn’t.

Read more