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.