Back

Git Flow Workflow: The Best Practice Guide

5 min read

In modern software development, version control is not just a backup tool for code, but the very cornerstone of team collaboration. Among various Git branching models, Git Flow, with its rigorous structure and clear release rhythm, has become the preferred choice for many large-scale projects and mid-sized teams.

This article will provide an in-depth, illustrated analysis of the core concepts and best practices of Git Flow, helping your team establish an efficient and reliable code management standard.


1. What is Git Flow?

Git Flow is a Git-based branching model proposed by Vincent Driessen in 2010. By defining clear branch roles and strict merge rules, it is specifically designed to manage complex software release cycles.

If your project has a clear release cycle (such as versioned releases like V1.0, V2.0), or needs to maintain older versions while developing new ones, Git Flow will be highly suitable for you.


2. Core Branching Model & Diagram

The core of Git Flow lies in its five types of branches. Let’s build an intuitive understanding through a global relationship diagram:

1. The Main Branches

In Git Flow, two branches have a permanent lifespan:

main (or master)

Always in a production-ready state. Only thoroughly tested code can be merged into this branch. Every merge to main is typically tagged with a version number.

develop

The integration branch for daily development. It contains all the latest feature code ready for the next release. When the code on develop stabilizes and is ready for release, it is merged back into main.

2. Supporting Branches

Supporting branches should be deleted immediately after completing their specific tasks to avoid branch pollution:

feature/* (Feature Branches)

Attribute Description
Source develop
Destination develop

Used to develop new features. Each new feature should be developed on a separate branch. Once development is complete, it is merged back into develop via a Pull Request (PR) and immediately deleted.

release/* (Release Branches)

Attribute Description
Source develop
Destination main and develop

When develop has accumulated enough new features and is ready for a version release, a release branch is branched off (e.g., release/v1.2). Only bug fixes, documentation updates, and version bumps are allowed on this branch; developing new features is strictly prohibited. Once testing passes, it is merged into main and tagged for release, as well as merged back into develop to ensure fixes are synchronized. Finally, the branch is deleted.

hotfix/* (Hotfix Branches)

Attribute Description
Source main
Destination main and develop

When an urgent bug occurs in the live production environment (main branch) and needs immediate fixing, this branch is cut from main. Once fixed, it is immediately merged back into main for an emergency release (tagged with a new version) and also merged back into develop to prevent the bug from regressing in the next release. Finally, the branch is deleted.


3. Core Rules of Git Flow Best Practices

Understanding the model is only the first step; implementation is key. Here are the golden rules for teams practicing Git Flow:

🚨 1. No Direct Commits

Strictly Prohibited

Never run git push directly to main and develop branches.

All changes to these two core branches must be made through Merge Requests / Pull Requests (PRs). Set up Branch Protection rules on code hosting platforms (like GitLab, GitHub) to enforce this.

🔍 2. Mandatory Code Review

When a feature branch is merged into develop, it must be reviewed by at least one other team member. This is not only for catching bugs, but is also the best opportunity for knowledge sharing and unifying code style.

🏷️ 3. Standardized Naming & Commit Messages

Branch Naming Convention: Use prefixes to clarify the branch type.

feature/JIRA-123-add-payment-gateway
release/v2.1.0
hotfix/fix-login-crash

Commit Message Convention: Conventional Commits are recommended.

feat: add user login functionality
fix: correct payment calculation on order page
docs: update API endpoints documentation
chore: upgrade dependency versions

♻️ 4. Keep Branch Lifespans Short

The lifespan of a feature branch should not be too long (ideally no more than a week). If a feature is large, break it down into multiple small, independently deliverable features. A feature branch left unmerged for too long leads to painful conflict resolution (Merge Hell).

♻️ 5. Sync Remote Code Frequently

While developing on a feature branch, get into the habit of running the following commands daily to detect and resolve conflicts early, rather than letting them pile up until you open a PR:

Terminal window
# Option 1: merge (keeps merge commit history)
git pull origin develop
# Option 2: rebase (maintains linear history, recommended)
git fetch origin
git rebase origin/develop

🎯 6. Hotfixes and Releases Must Be Merged “Both Ways”

This is the most common mistake made by beginners: fixing a production bug (merged to main) but forgetting to merge it back into develop, causing the old bug to reappear in the next release.

⚠️ Important Reminder

Any code that enters main, whether a release or a hotfix, must be synchronized back into develop.


4. Common Workflow Scenarios Demonstration

Scenario A: Developing a New Feature (Feature)

Terminal window
# 1. Branch off from develop
git checkout -b feature/user-profile develop
# 2. Develop and commit
git commit -m "feat: add user profile page"
# 3. Push and create a PR/MR requesting to merge into develop
git push origin feature/user-profile
# 4. Once reviewed and merged, delete the branch
git branch -d feature/user-profile
git push origin --delete feature/user-profile

Scenario B: Preparing a New Version Release (Release)

Terminal window
# 1. Once develop features are ready, create release branch from develop
git checkout -b release/v1.1.0 develop
# 2. Only perform version bumps, bug fixes, and documentation updates
git commit -m "chore: bump version to v1.1.0"
git commit -m "fix: resolve edge case in payment flow"
# 3. Merge to main and Tag it
git checkout main
git merge release/v1.1.0
git tag -a v1.1.0 -m "Release v1.1.0"
git push origin main --tags
# 4. Sync back to develop
git checkout develop
git merge release/v1.1.0
# 5. Delete release branch
git branch -d release/v1.1.0
git push origin --delete release/v1.1.0

Scenario C: Urgently Fixing a Live Bug (Hotfix)

Terminal window
# 1. Branch off from main
git checkout -b hotfix/v1.1.1 main
# 2. Fix bug and test
git commit -m "fix: resolve memory leak on login"
# 3. Merge to main and Tag it
git checkout main
git merge hotfix/v1.1.1
git tag -a v1.1.1 -m "Hotfix v1.1.1"
git push origin main --tags
# 4. Sync back to develop (Critical step, do not skip!)
git checkout develop
git merge hotfix/v1.1.1
# 5. Delete hotfix branch
git branch -d hotfix/v1.1.1
git push origin --delete hotfix/v1.1.1

5. Summary & Selection Advice

Advantages

  • Strict branch definitions with distinct responsibilities for development, testing, and release stages.
  • Highly suitable for supporting multiple versions concurrently and products with fixed release cycles.
  • Easy to trace historical versions, providing high security for the production environment.

Limitations (When Not to Use)

For SaaS projects with high CI/CD requirements that need to release multiple times a day, Git Flow is overly heavy. Consider the following alternatives:

Model Applicable Scenarios Core Philosophy
GitHub Flow Small teams, continuous deployment Only main + feature branches, PR is release
Trunk Based Development High-frequency releases, mature DevOps teams Everyone commits directly to trunk, relies on Feature Flags
Git Flow Versioned products, multi-version maintenance Strict branch roles and release pipelines

One-Sentence Summary

Git Flow is like a precision assembly line—the process is strict and even slightly tedious, but as long as everyone follows the rules, it guarantees that code arrives smoothly and on time in the production environment.

Tags: GitBest PracticesEngineering
Share to: