Git Workflows

By Vishvesh Patel · DevOps EngineerUpdated September 16, 2026

GitFlow, GitHub Flow and trunk-based development compared honestly, which suits which team, why long-lived branches hurt, and feature flags.

Why Git Workflows Matter

Git gives you branches and merges, but a workflow decides how a team should use them.

This lesson compares three common models:

  • GitFlow
  • GitHub Flow
  • Trunk-Based Development

Tip: Pick the lightest workflow that still fits your release process. More branches are only useful when they solve a real coordination problem.

GitFlow

GitFlow is a structured workflow designed for teams with planned releases.

Its long-lived branches are:

  • main for production-ready history
  • develop for ongoing integration

Supporting branches include:

  • feature/*
  • release/*
  • hotfix/*

How GitFlow Works

A feature usually starts from develop:

git switch develop
git switch -c feature/add-audit-logs

When the feature is ready, it goes back into develop. Later, the team creates a release branch:

git switch develop
git switch -c release/2.4.0

For urgent production issues, a hotfix starts from main:

git switch main
git switch -c hotfix/fix-payment-timeout

The fix is merged into main and back into develop.

When GitFlow Fits

GitFlow works well when:

  • releases are scheduled rather than continuous
  • multiple supported versions exist
  • teams want a dedicated release stabilization phase
  • enterprise approval processes require more separation

The trade-off is more branch overhead.

GitHub Flow

GitHub Flow is a simpler PR-based model built around one main long-lived branch: main.

The usual steps are:

  1. branch from main
  2. make changes on a short-lived feature branch
  3. open a pull request
  4. review and test
  5. merge back to main

Example:

git switch main
git pull origin main
git switch -c feature/update-runbook
git add .
git commit -m "docs: update deployment runbook"
git push -u origin feature/update-runbook

When GitHub Flow Fits

GitHub Flow is a strong choice when:

  • the team is small or medium-sized
  • pull requests are the main review mechanism
  • main is kept releasable
  • CI gives quick feedback

Note: GitHub Flow depends on a healthy main branch. Fast tests and code review are important because work merges there frequently.

Trunk-Based Development

Trunk-Based Development centers on one integration branch, usually main or trunk, and very short-lived branches.

Its main ideas are:

  • integrate small changes often
  • avoid long-lived branch drift
  • keep merges frequent and low risk
  • use feature flags for incomplete work

Example:

git switch main
git pull origin main
git switch -c feature/add-cache-metric
git commit -am "feat: add cache hit metric behind feature flag"
git push -u origin feature/add-cache-metric

Feature Flags in Trunk-Based Development

Because teams merge early, unfinished work is often hidden behind flags.

FEATURE_NEW_DASHBOARD=false

Feature flags separate deployment from release. Code can be merged and even deployed without being visible to users yet.

When Trunk-Based Development Fits

This workflow is often best for teams that:

  • deploy frequently
  • invest heavily in CI/CD
  • want fewer merge conflicts
  • can break large work into small safe increments

Its biggest challenge is discipline. Large long-running branches work against the model.

Choosing the Right Workflow

Small Team

A small team often starts best with GitHub Flow because it is simple.

Enterprise Team

A larger organization with formal release windows often prefers GitFlow.

CI/CD-Heavy Team

A team shipping many times per day often benefits most from Trunk-Based Development or a lightweight GitHub Flow variant, because both keep integration frequent.

Quick Comparison

WorkflowLong-Lived BranchesBest For
GitFlowmain, developplanned releases, enterprise coordination
GitHub FlowmainPR-based teams, simpler delivery
Trunk-Based Developmentmain or trunkfast CI/CD and short-lived branches

What You Should Remember

GitFlow adds structure for releases and hotfixes, GitHub Flow keeps things simple around main and pull requests, and Trunk-Based Development pushes toward very fast integration with short-lived branches and feature flags. The best workflow is the one that matches your release cadence, team size, and automation maturity.

Test Your Understanding

Exercise

Exercise 1: Recognizing GitFlow

Which workflow uses `main`, `develop`, `feature/*`, `release/*`, and `hotfix/*` branches as core concepts?

Exercise

Exercise 2: Matching a workflow to frequent deployment

A team deploys many times per day and wants small, fast integrations with feature flags. Which workflow is the best match?

Exercise

Exercise 3: Choosing for a small team

A small product team wants one main branch, short-lived feature branches, and pull-request-based review. Which workflow should they start with?


Frequently Asked Questions

What is the difference between GitFlow, GitHub Flow and trunk-based development?

They differ in how many long-lived branches exist. GitFlow keeps main, develop, plus release and hotfix branches. Heavy, but it models versioned software with several supported releases. GitHub Flow keeps only main plus short-lived feature branches, each merged via pull request and deployed on merge. Trunk-based development goes furthest: everyone commits to main at least daily, with incomplete work hidden behind feature flags rather than branches. The trade is branch isolation against integration pain. The longer a branch lives, the worse its merge.

Which Git workflow should a small team use?

GitHub Flow, in almost every case. One protected main, a short-lived branch per change, a pull request for review, deploy on merge. It is enough process to keep main releasable and little enough that nobody spends time on branch bookkeeping. GitFlow's develop and release branches only pay off when you genuinely maintain multiple versions in production simultaneously, and adopting it without that need is the most common case of a workflow costing more than it returns.

Is GitFlow still recommended?

Only for software with real release management. Desktop applications, on-premise products, anything where several versions are supported at once and hotfixes must land on old releases. Its author has said as much: for continuously deployed web services the extra branches add ceremony without benefit. If you deploy from main several times a week, GitHub Flow or trunk-based development fits the reality better, and the release branch you are maintaining is usually just a delay.

What are feature flags and why does trunk-based development need them?

A feature flag is a runtime switch that decides whether new code paths are active, letting you merge unfinished work into main safely because it is simply off. Trunk-based development depends on them: if everyone integrates daily, there is no long branch in which to hide an incomplete feature, so the hiding has to move into the code. The cost is real, flags accumulate, and each one doubles the possible states, so removing them once a feature ships has to be part of the process.

How long should a feature branch live?

A day or two; a week at the outside. Merge difficulty grows with the square of the time, roughly, because both your branch and main keep moving and the overlap compounds. If a change cannot be finished in that window, split it into separately shippable pieces, a refactor, then the behaviour behind a flag, rather than letting the branch run. "Long-lived feature branch" is close to a synonym for "painful merge".

How do branch protection rules fit into a workflow?

They are what makes the workflow actually happen rather than being a document people mean to follow. On main, typical rules require a pull request rather than a direct push, at least one approving review, passing status checks, and an up-to-date branch before merge. Setting the merge strategy, squash, merge commit or rebase, at the repository level is worth doing too, since leaving it per-developer produces a history with all three. Enforce it centrally; local hooks can be bypassed with --no-verify.

Continue Learning

Explore Related Topics

When it breaks

Related Resources