GitFlow is a branching model built for a world of scheduled releases and infrequent deployments. That world is gone. Here is a precise account of what it costs and why teams are still paying it.
Vincent Driessen published the original GitFlow post in 2010. It was a thoughtful response to a real problem: coordinating releases across a large team when deployments are infrequent, scheduled events and multiple versions need to be maintained simultaneously. The model made sense in that context. It was not designed for continuous delivery. It was not designed for teams that deploy to production daily. It was not designed for the way most software teams work now.
Driessen added a note to his own post acknowledging exactly this. If your team practises continuous delivery, he wrote, GitFlow is not the right model. The creator of GitFlow said this. In writing. On the original post. Teams are still adopting it.
"If your team is doing continuous delivery of software, I would suggest adopting a much simpler workflow (like GitHub flow) instead of trying to use git-flow." The model's creator deprecated it for modern delivery teams. The industry did not get the memo.
What GitFlow actually requires.
Before examining what it costs, it is worth being precise about what GitFlow is. The model defines five branch types with specific rules governing their creation, lifetime, and merge targets:
On paper this looks structured. In practice it is five branch types, four merge directions, and a set of rules complex enough that a dedicated CLI tool — git flow — was created to manage the ceremony so developers would not make mistakes doing it manually. When a branching model requires its own tooling to execute correctly, that is a signal worth examining.
Where the value disappears.
Production is down. Here is your process.
The hotfix workflow is where GitFlow's structural problems become most visible. A production incident is already a high-stress, time-sensitive situation. GitFlow's response is a multi-step, multi-target merge sequence that must be executed correctly under pressure:
hotfix/x.x.x off master. Not develop. Master. Because develop may contain unreleased work that must not go to production. First decision point under pressure.This is a process optimised for failure under exactly the conditions when failure is most costly. The model that is supposed to protect production requires the most cognitive overhead at the moment of highest stress.
The ceremony looks like control.
GitFlow persists for the same reason any complex process persists: it feels rigorous. The diagram is impressive. The branch types have clear names and defined purposes. There are rules. There are gates. A new engineer joining a GitFlow team sees a structured model and infers that the team is disciplined. The inference is wrong, but it is understandable.
The process has become the product. Teams that run GitFlow spend measurable engineering time managing the branching model — resolving the conflicts it generates, maintaining the consistency between its branches, executing its merge sequences correctly. That time is not spent shipping software. It is spent maintaining the infrastructure of a process that was designed to support shipping and has become an obstacle to it.
The longer a team runs GitFlow, the harder it is to leave. The develop branch accumulates work that has never touched production. The gap between develop and master grows. The team loses confidence in both branches. Merge conflicts become routine. Engineers stop asking whether the model is serving them because the cost of changing it feels higher than the cost of continuing. The sunk cost reasoning is not always wrong — migration is genuinely expensive. But continuing is not free.
There is also an ego dimension. GitFlow was set up by someone who understood the model, probably a senior engineer or architect. It represents a decision. Questioning it means questioning that person's judgement, which is politically uncomfortable in most teams. So the model persists not because it is working but because removing it requires a conversation nobody wants to have.
Simple is not naive.
The alternative to GitFlow is not a lack of structure. It is a simpler structure that carries less overhead and creates fewer points of failure:
One mainline: master. Master equals what is in production, always. Short-lived branches for development, named for the unit of work, dead within a day. PRs as the enforcement surface for CI policy — not necessarily for human review. Merge on green. Feature flags for work that is complete but not yet released to users. No develop branch. No release branches. No hotfix branches with multi-target merge requirements. One branch, one truth, one process that does not change under pressure.
This is not simpler because simplicity is a value in itself. It is simpler because the complexity GitFlow adds does not pay for itself. The isolated develop branch does not prevent integration problems — it defers them. The release branch does not protect master — it creates a third surface to maintain. The hotfix procedure does not make incident response faster — it adds steps at the worst possible time.
Every piece of complexity in a development process should be justified by a concrete problem it solves that a simpler approach cannot. For most teams, GitFlow's complexity solves problems those teams do not have, and creates problems they did not have before.
Getting out is hard but the cost of staying is higher.
The most common objection to leaving GitFlow is migration cost. The develop branch contains work that has not been released. Release branches may be in flight. The team's muscle memory is built around the model. All of this is real.
The migration cost is paid once. The cost of continuing to run GitFlow is paid on every hotfix, every release branch merge, every conflict generated by the develop-to-feature-branch isolation. The question is not whether migration is expensive. It is whether the ongoing cost of the current model exceeds the one-time cost of leaving it. For most teams it does, within months.
The migration path is not complicated. Cut the develop branch free. Make master the integration point going forward. Work through any in-flight release branches using the existing process for the last time. Establish the CI enforcement infrastructure on master before you remove the old guard rails. Ship the first hotfix under the new model — once the team has done it once, the simplicity is self-evident.
The pantomime ends the moment you stop performing it. The lines do not need to be forgotten gradually. The curtain can just come down.