Git Flow vs. Reality: Common Issues and Practical Fixes

Devaka Dabare
7 min readFeb 8, 2025

--

Git Flow is a popular branching strategy for managing software development, introduced by Vincent Driessen. It provides a structured way to handle feature development, releases, and hotfixes.

However, in practice, teams often face challenges like long-lived branches, complex merge conflicts, and slow integrations. These issues can delay development, increase bugs, and complicate deployments.

In this article, we’ll explore common Git Flow problems and practical solutions to improve workflow efficiency. If you struggle with branching complexity, conflict resolution, or slow releases, this guide will help you navigate those challenges effectively.

Understanding Git Flow Branching

Git Flow Branching

Git Flow is a structured branching model that systematically helps teams manage feature development, releases, and bug fixes. The key branches in Git Flow include:

  1. Master Branch: This is the main production-ready branch.
    Only stable, released code is merged here.
  2. Develop Branch: Acts as an integration branch where new features are merged. Represents the latest completed development work.
  3. Feature Branches (e.g., Feature A): Created from develop to work on new features or enhancements. Once completed, it is merged back into develop.
  4. Release Branches (e.g., Release V1): Created from develop when preparing for a new version release.Allows bug fixes before merging into masterand develop.
  5. Hotfix Branches (Not shown in the diagram but part of Git Flow): Created from the masterto fix critical issues in production.Merged back into both masterand developafter the fix.

How Branching Happens in Git Flow

In Git Flow, branches are structured hierarchically, where each branch serves a specific purpose in the development and release lifecycle. Below is a breakdown of how branching works:

  1. Master as the Parent Branch
    The master branch is the primary, stable branch that holds production-ready code. It serves as the parent branch from which the Develop branch is created.
  2. Developing New Features
    A Develop branch is created from master. This acts as the main working branch where developers integrate their work.The masterbranch is the head branch for develop, meaning all new development originates from this point.When working on a new feature, a Feature branch (e.g., feature-A) is created from develop.Here, the developbranch serves as the parent branch for all feature branches.
  3. Merging Feature Branches
    After development is completed on a feature, it is merged back into the develop branch.
    This ensures all new features are integrated before preparing for a release.
  4. Creating a Release Branch
    Once enough features are merged into develop, a Release branch (e.g., release-V1) is created from develop.
    The release branch is used for final testing, bug fixes, and preparing for deployment.
    (In real-world scenarios, teams might have QA (Quality Assurance) or UAT (User Acceptance Testing) branches between developand release, but for simplicity, we are considering just develop.)
  5. Deploying the Release and Merging Changes
    Once the release is finalized, it is deployed from the release branch.
    After deployment, the Release branch is merged back into master, ensuring that the production branch has the latest changes.
    The changes are then merged back into developto keep it updated with what is in production.

Issues in Git Flow Branching and Their Challenges

Issue #1: Feature Dependencies Preventing Selective Releases

Git Flow Branching — Issue #1

Scenario:

  • Feature A is branched from develop, changes are made, and it is merged back.
  • Feature B is branched from develop after Feature A was merged.
  • During testing (QA), Feature A is found to have critical bugs, while Feature B is working fine and the client requests an immediate release.

Problem:

Since Feature B was branched after Feature A was merged into develop, it already includes the changes from Feature A.

  • If we proceed with releasing Feature B, we will also be releasing Feature A unintentionally, including its bugs.
  • If we want to revert Feature A, we cannot do it without affecting Feature B, since their histories are now intertwined.

Why This Happens?

  • Git Flow merges all completed features intodevelop, which means any new branch taken from develop inherits all previously merged changes.
  • There is no easy way to separate Feature B from Feature A once it has been branched.

Issue #2: Merge Conflicts and Unwanted Feature Dependencies

Scenario:

  • Feature A and Feature B are branched from develop at the same time.
  • After development, Feature A is merged into develop first.
  • Now, when trying to merge Feature B into develop, merge conflicts occur.
  • To resolve this, we normally pull the latest develop into Feature B, fix conflicts, and then merge Feature B back into develop.

Problem:

  • When pulling from develop, Feature B now contains changes from Feature A, even though they were developed separately.
  • If we only want to merge Feature B, it will still contain Feature A’s changes because we merged the latest develop.
  • If Feature A has issues or is not meant to be released yet, Feature B gets affected unnecessarily.

Why This Happens?

  • In Git, when a feature branch merges into develop, all new branches inheriting from develop after that get those changes.
  • Merge conflicts force developers to pull develop into feature branches, which causes unwanted dependencies between independent features.
Photo by Shamin Haky on Unsplash

Proposed Solution: Isolating Feature Branches from Master for Better Control

Enhaced git flow

In this improved Git Flow model, we branch feature branches directly from master instead of develop. This solves Issue #1, where unwanted dependencies between features were causing release complications.

How This Solution Works (Diagram Explanation)

  • Every Feature Branch (Feature A, Feature B, etc.) now branches out from master instead of develop.
  • This ensures that each feature remains isolated from the other features under development.
  • Developers should regularly pull the latest changes from master before pushing their code to avoid missing released updates.
  • Once development is completed:
  1. The feature branch is merged into develop for integration testing.
  2. If it passes QA and is ready for release, it is merged into the Release branch.
  3. If the feature is not ready, it is not merged into the release branch, avoiding the risk of shipping unfinished work.

Why Does This Solve Issue #1?

Previously, all feature branches were based ondevelop, so if one feature had issues, others inherited those issues.

  • Now, each feature is completely independent and can be merged only when it’s ready.
  • If Feature A has bugs, it won’t affect Feature B, since Feature B was never dependent on develop.
  • Only features that pass QA and are approved for the next release are merged into the release branch.

Handling Collaboration on Large Features

For large features involving multiple developers, we introduce sub-feature branches:

  1. The main feature branch (e.g., feature/main-feature-A) is created from master.
  2. Developers can create sub-feature branches (e.g., feature/A-sub-1, feature/A-sub-2) from the main feature branch.
  3. These sub-features merge back into the main feature branch, keeping work organized.
  4. When the feature is complete, the main feature branch is merged into develop or release as needed.

Why This Solution Is Cleaner and More Efficient?

Feature branches stay isolated from other features, preventing unwanted dependencies.
Selective releases become easier, we can decide which features go into a release without worrying about conflicts.
QA is more controlled, only features that pass testing are merged into the release.
Scalability improves, developers working on the same feature can collaborate efficiently without blocking others.

Handling Merge Conflicts Without Polluting Feature Branches

Conflict resolving

How It Works (Diagram Explanation)

  1. Do NOT pull from develop/qa directly into the feature branch.
  2. Instead, create a new conflict resolution branch (dev_conflict/FT_A) from the feature branch (Feature A).
  3. Pull the latest changes from develop/qa into the conflict branch.
  4. Resolve conflicts in the conflict branch (dev_conflict/FT_A).
  5. Once resolved, merge the conflict branch into develop/qa.
  6. The original feature branch (Feature A) remains clean and unchanged.
  7. If the feature is approved for release, a PR is raised from the original feature branch to release or qa.

Why Does This Approach Work?

Feature branches remain clean without unnecessary merges.
Conflict resolution happens in an isolated branch, making debugging easier.
No risk of accidentally merging unwanted changes into a feature branch.
Keeps feature history clean and organized, making rollbacks easier if needed.

Photo by Ben Mullins on Unsplash

Conclusion: Improving Git Flow for a Smoother Workflow

Git Flow provides a structured approach to software development, but real-world challenges like unwanted feature dependencies, merge conflicts, and selective releases can complicate the process.

In this article, we explored common Git Flow issues and practical solutions to overcome them:
Isolating feature branches from master to prevent unwanted dependencies.
Selective merging to ensure only approved features make it to production.
Using conflict resolution branches instead of polluting feature branches.

By following these strategies, teams can keep their Git history clean, manage releases more effectively, and reduce the risk of deployment issues.

Adapting Git Flow to fit your team’s needs will lead to a more efficient, scalable, and conflict-free development process.

💬 If you found this article helpful, consider supporting it by sharing it with your team!
📢 Have questions or suggestions? Drop a comment below, and let’s discuss!

Happy Coding! 🚀

--

--

Devaka Dabare
Devaka Dabare

Written by Devaka Dabare

Senior Software Engineer @ Orel IT

No responses yet