Practicing Git Branch Strategies

intermediate | 120 min read | 2025.12.02

What You’ll Learn in This Tutorial

  • Basic branch operations
  • Feature Branch Workflow
  • Differences between Git Flow and GitHub Flow
  • When to use merge vs rebase
  • Resolving conflicts

What is a Branch Strategy? Why is it Important?

History of Branch Strategies

Branch strategies gained attention in the late 2000s as team development became more complex.

In 2010, Vincent Driessen proposed Git Flow in his article “A successful Git branching model”. This became widely adopted as the first systematic branch strategy.

Later, GitHub proposed the simpler GitHub Flow in 2011. It gained support as an optimal model for teams doing continuous deployment.

“Branch strategies should be chosen based on the team’s workflow. There is no one-size-fits-all strategy.” — Vincent Driessen, 2020 follow-up article

Why Branch Strategies Are Needed

  1. Parallel development: Develop multiple features simultaneously
  2. Risk isolation: Isolate unstable code from the mainline
  3. Code review: Quality assurance through pull requests
  4. Release management: Control deployment to production

Comparison of Major Branch Strategies

StrategyComplexitySuitable TeamsDeploy Frequency
Feature BranchLowSmall teamsVaries
GitHub FlowLowContinuous deploymentDaily to several times/week
Git FlowHighClear release cyclesWeekly to monthly
Trunk BasedMediumLarge, mature teamsDaily to multiple times/day

Basic Branch Operations

Creating and Switching Branches

# List branches
git branch

# List including remote branches
git branch -a

# Create new branch
git branch feature/login

# Switch branch
git checkout feature/login

# Create and switch simultaneously (recommended)
git checkout -b feature/login

# New command from Git 2.23+ (recommended)
git switch -c feature/login
git switch feature/login

Official Documentation: git-branch

Branch Naming Conventions

Using consistent naming conventions across the team is important:

# Feature development
feature/user-authentication
feature/payment-integration

# Bug fixes
fix/login-button-crash
bugfix/memory-leak

# Emergency fixes
hotfix/security-vulnerability

# Release preparation
release/v1.2.0

# Experimental features
experiment/new-algorithm

Best Practice: Branch names should be lowercase, hyphen-separated, and include issue numbers for easy tracking (e.g., feature/JIRA-123-add-login)

Remote Branch Operations

# Show including remote branches
git branch -a

# Checkout remote branch locally
git checkout -b feature/login origin/feature/login

# Or (Git 2.23+)
git switch feature/login  # Automatically tracks remote

# Push branch to remote
git push -u origin feature/login

# Delete remote branch
git push origin --delete feature/login

# Delete local branch
git branch -d feature/login

# Force delete unmerged branch
git branch -D feature/login

Checking Branch Status

# Show diff between branches
git diff main..feature/login

# Show merged branches
git branch --merged

# Show unmerged branches
git branch --no-merged

# Show last commit of each branch
git branch -v

Feature Branch Workflow

The most basic branch strategy. Create a branch for each feature and merge to main when complete.

Workflow Diagram

gitGraph
    commit
    branch feature/A
    commit
    commit
    commit
    commit
    checkout main
    merge feature/A
    commit

Practical Scenario: Adding Login Feature

# 1. Update main branch
git checkout main
git pull origin main

# 2. Create feature branch
git checkout -b feature/login

# 3. Implement and commit
# (edit code)
git add .
git commit -m "feat: Add login form component"

# (more implementation)
git add .
git commit -m "feat: Add login API integration"

# (add tests)
git add .
git commit -m "test: Add login validation tests"

# 4. Push to remote
git push -u origin feature/login

# 5. Create pull request (on GitHub)

# 6. Merge after review

Pull Request Best Practices

“Keep pull requests small. Ideally, reviewers should be able to review in under 20 minutes.” — Google Engineering Practices

  1. Appropriate size: Aim for 200-400 lines
  2. Single purpose: One feature/fix per PR
  3. Detailed description: Include background, changes, and how to test
  4. Self-review: Check yourself before submitting

Git Flow

A strategy for projects with clear release cycles. Proposed by Vincent Driessen in 2010.

Main Branches

flowchart TB
    main["main (or master)"]
    develop["develop<br/>(development integration branch)"]
    feature["feature/*<br/>(feature development)"]
    release["release/*<br/>(release preparation)"]
    hotfix["hotfix/*<br/>(emergency bug fixes)"]

    main --> develop
    develop --> feature
    develop --> release
    main --> hotfix
BranchPurposeBranches FromMerges To
mainProduction releases--
developDevelopment integrationmainmain, release
feature/*Feature developmentdevelopdevelop
release/*Release preparationdevelopmain, develop
hotfix/*Emergency fixesmainmain, develop

Practicing Git Flow

# Create feature branch from develop
git checkout develop
git checkout -b feature/user-profile

# After feature complete, merge to develop
git checkout develop
git merge --no-ff feature/user-profile
git branch -d feature/user-profile

# Release preparation
git checkout -b release/1.0.0 develop

# Update version number, bug fixes, etc.
git commit -m "chore: Bump version to 1.0.0"

# Complete release
git checkout main
git merge --no-ff release/1.0.0
git tag -a v1.0.0 -m "Version 1.0.0"

git checkout develop
git merge --no-ff release/1.0.0
git branch -d release/1.0.0

# Emergency fix (Hotfix)
git checkout main
git checkout -b hotfix/security-fix

# After fix
git checkout main
git merge --no-ff hotfix/security-fix
git tag -a v1.0.1 -m "Security patch"

git checkout develop
git merge --no-ff hotfix/security-fix
git branch -d hotfix/security-fix

git-flow Tool

The git-flow command simplifies operations:

# Install
# macOS
brew install git-flow

# Ubuntu
apt install git-flow

# Initialize
git flow init

# Feature development
git flow feature start user-profile
git flow feature finish user-profile

# Release
git flow release start 1.0.0
git flow release finish 1.0.0

# Hotfix
git flow hotfix start security-fix
git flow hotfix finish security-fix

When Git Flow Applies

Suitable:

  • Regular release cycles
  • Need to support multiple versions
  • Have a QA team

Not suitable:

  • Continuous deployment
  • Small teams
  • Web apps running only latest version

Vincent Driessen’s 2020 follow-up: “Now that continuous deployment has become common in web development, Git Flow is overkill for many projects. Please consider simpler models like GitHub Flow.”

GitHub Flow

A simple strategy suitable for continuous deployment. Officially recommended by GitHub.

Workflow Diagram

gitGraph
    commit
    branch PR-1
    commit
    commit
    commit
    checkout main
    merge PR-1
    branch PR-2
    commit
    commit
    commit
    checkout main
    merge PR-2
    commit

The 6 Rules

  1. main branch is always deployable
  2. Feature development branches from main
  3. Push to remote regularly
  4. Code review via pull request
  5. Merge to main after review
  6. Deploy immediately after merge

GitHub Official Blog: GitHub Flow

Practicing GitHub Flow

# Create feature branch from main
git checkout main
git pull origin main
git checkout -b add-dark-mode

# Develop and commit (small and frequent)
git add .
git commit -m "feat: Add dark mode toggle"
git push -u origin add-dark-mode

# Create pull request (on GitHub)
# Code review
# CI/CD pipeline runs automatically

# After PR approval, merge & deploy
# Delete branch after merge
git checkout main
git pull origin main
git branch -d add-dark-mode

When GitHub Flow Applies

Suitable:

  • Continuous deployment
  • Running only latest version
  • Small to medium teams

Trunk Based Development

A strategy used by large teams at Google, Facebook, etc.

Features

  • Merge directly to main branch (trunk) or from short-lived branches
  • Branches are merged within 1-2 days
  • Large features controlled via feature flags
gitGraph
    commit
    branch short-1
    commit
    checkout main
    merge short-1
    branch short-2
    commit
    checkout main
    merge short-2
    branch short-3
    commit
    checkout main
    merge short-3
    commit
    branch short-4
    commit
    checkout main
    merge short-4
    commit

Reference: trunkbaseddevelopment.com

Merge vs Rebase

Merge

Preserves history and creates merge commits.

# Merge feature/login into main
git checkout main
git merge feature/login

# Always create merge commit (--no-ff)
git merge --no-ff feature/login

Result:

gitGraph
    commit
    branch feature
    commit
    commit
    checkout main
    merge feature
    commit

Rebase

Rewrites history to be linear.

# Incorporate latest main into feature branch
git checkout feature/login
git rebase main

# Interactive rebase (organize commits)
git rebase -i HEAD~3

Result:

gitGraph
    commit
    commit
    branch feature
    commit
    commit

Which to Use?

ScenarioRecommendedReason
Integration to shared branchMergePreserves history, safe
Organizing local commitsRebaseClean history
Incorporate latest main into featureRebaseLinear history
Already pushed commitsMerge onlyRewriting history is dangerous

Golden Rule: “Never rebase commits shared with others”

Organizing Commits with Interactive Rebase

git rebase -i HEAD~3

Editor opens:

pick abc1234 WIP: work in progress
pick def5678 fix: typo
pick ghi9012 feat: Add login feature

# Commands:
# p, pick = use commit
# r, reword = edit message
# s, squash = combine with previous commit
# f, fixup = combine with previous (discard message)
# d, drop = delete commit
# Organize commits
pick abc1234 WIP: work in progress
squash def5678 fix: typo
squash ghi9012 feat: Add login feature

Resolving Conflicts

How Conflicts Occur

flowchart TB
    A["main: Hello World"] --> B["Hello Everyone<br/>(someone else merged)"]
    A --> C["feature: Hello Universe<br/>(your change)"]
    B --> D["Conflict occurred!"]
    C --> D

Conflict Resolution Steps

# When conflict occurs during merge
git status  # Check conflicting files

# Edit files to resolve conflict

Conflict markers:

<<<<<<< HEAD
Current branch content
=======
Content from branch being merged
>>>>>>> feature/login

After resolution:

# Stage resolved files
git add conflicted-file.js

# Complete merge
git commit -m "merge: Resolve conflict between header and footer"

# Or abort merge
git merge --abort

Conflict Resolution Best Practices

  1. Merge/rebase main frequently: Keep conflicts small
  2. Communicate: Consult beforehand when editing same files
  3. Use tools: VS Code, GitKraken, and other GUI tools
  4. Run tests: Always run tests after resolution

Conflict Resolution in VS Code

VS Code can visually resolve conflicts:

Accept Current Change  | Accept Incoming Change  | Accept Both Changes

Practice: Team Development Simulation

Simulate a scenario where two developers experience a conflict.

# 1. Initialize repository
mkdir team-dev-simulation
cd team-dev-simulation
git init
echo "# Team Project" > README.md
git add README.md
git commit -m "Initial commit"

# 2. Developer A's branch
git checkout -b feature/header
echo "<header>Header A</header>" > index.html
git add index.html
git commit -m "feat: Add header by Dev A"

# 3. Return to main and create Developer B's branch
git checkout main
git checkout -b feature/footer
echo "<footer>Footer B</footer>" > index.html
git add index.html
git commit -m "feat: Add footer by Dev B"

# 4. Merge feature/header first
git checkout main
git merge feature/header

# 5. Merge feature/footer (conflict occurs!)
git merge feature/footer
# CONFLICT (add/add): Merge conflict in index.html

# 6. Resolve conflict
# Edit index.html to include both changes
cat > index.html << 'EOF'
<header>Header A</header>
<footer>Footer B</footer>
EOF

git add index.html
git commit -m "merge: Resolve conflict between header and footer"

Branch Strategy Selection Guide

Answer Questions to Choose a Flow

  1. Do you deploy continuously?

    • Yes → GitHub Flow or Trunk Based
    • No → Consider Git Flow
  2. What is your release cycle?

    • Daily to several times/week → GitHub Flow
    • Weekly to monthly → Git Flow
    • Multiple times per day → Trunk Based
  3. What is your team size?

    • 1-5 people → GitHub Flow
    • 5-20 people → GitHub Flow or Git Flow
    • 20+ people → Trunk Based (feature flags required)

Common Mistakes and Anti-Patterns

1. Long-Lived Branches

# Anti-pattern: Branches not merged for weeks
# Conflicts become huge, merging becomes difficult

# Best practice: Merge frequently
git checkout feature/big-feature
git fetch origin
git rebase origin/main  # Do daily

2. Rebasing After Push

# Dangerous! Rewriting shared commits
git push origin feature/x
git rebase -i HEAD~3
git push --force  # Overwrites others' changes

# Safe: Use force-with-lease
git push --force-with-lease

3. Direct Commits to main

# Anti-pattern
git checkout main
git commit -m "Quick fix"

# Best practice: Always go through PR
git checkout -b fix/quick-fix
git commit -m "Quick fix"
git push -u origin fix/quick-fix
# Create PR

Official Documentation & Source

Tools

← Back to list