๐ŸŒฟ Git Strategy Guide

Branching Strategies, Rebase, and Best Practices Used by Top Companies

๐ŸŒฟ Git Branching Strategies

Choosing the right branching strategy is crucial for team productivity. Different strategies suit different team sizes, release cycles, and project types.

Complex

GitFlow

Multiple long-lived branches for structured release management.

Best for: Versioned software, mobile apps

Simple

GitHub Flow

Simple workflow with main + feature branches.

Best for: SaaS, web apps, startups

Simple

Trunk-Based

Everyone commits to main with short-lived branches.

Best for: Large teams, continuous deployment

Moderate

GitLab Flow

Environment branches for staged deployments.

Best for: Multi-environment, enterprise

๐Ÿ”€ GitFlow

GitFlow uses multiple long-lived branches for structured release management.

Branch Structure

main      โ†’ Production-ready code only
develop   โ†’ Integration branch for features
feature/* โ†’ New features (branch from develop)
release/* โ†’ Prepare for release (branch from develop)
hotfix/*  โ†’ Emergency fixes (branch from main)

Visual Flow

main โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ
         โ”‚   v2.0         โ–ฒ   v2.1         โ–ฒ   v2.2
         โ”‚                โ”‚                โ”‚
hotfix   โ”‚      โ—โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ—                โ”‚
         โ”‚      โ”‚                          โ”‚
         โ–ผ      โ–ผ                          โ”‚
develop โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ–ถ
         โ”‚     โ–ฒ  โ”‚     โ–ฒ                  โ–ฒ
         โ”‚     โ”‚  โ”‚     โ”‚                  โ”‚
feature  โ—โ”€โ”€โ”€โ”€โ”€โ—  โ—โ”€โ”€โ”€โ”€โ”€โ—                  โ”‚
         โ”‚              โ–ฒ                  โ”‚
release                 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ—

Pros & Cons

โœ… ProsโŒ Cons
Clear separation of concernsComplex, many branches
Parallel developmentLong-lived branches = merge conflicts
Structured release processSlow release cycles
Good for versioned softwareOverkill for continuous deployment
Supports multiple versionsSteep learning curve

๐Ÿ™ GitHub Flow

A simplified workflow focused on continuous deployment.

Visual Flow

main โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ—โ”€โ”€โ”€โ”€โ–ถ
         โ”‚    โ–ฒ    โ”‚    โ–ฒ    โ”‚    โ–ฒ
         โ”‚    โ”‚    โ”‚    โ”‚    โ”‚    โ”‚
feature  โ—โ”€โ”€โ”€โ”€โ—    โ—โ”€โ”€โ”€โ”€โ—    โ—โ”€โ”€โ”€โ”€โ—

WORKFLOW:
1. Create branch from main
2. Make changes, commit
3. Open Pull Request
4. Review & discuss
5. Deploy and test
6. Merge to main

Pros & Cons

โœ… ProsโŒ Cons
Simple, easy to understandNo separate develop branch
Fast deploymentRequires robust CI/CD
Continuous deployment friendlyMain must always be deployable
Quick feedback loopLess structure for complex releases
Minimal branch managementNo version support

๐Ÿš€ Trunk-Based Development

Everyone commits to a single branch (trunk/main) with very short-lived feature branches.

Visual Flow

main โ”€โ”€โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ—โ”€โ”€โ–ถ
(trunk)  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ  โ–ฒ
         โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ”‚  โ”‚
         โ—  โ—  โ—  โ—  โ—  โ—  โ—  โ—  โ—  โ—  โ—  โ—  โ—
         
         Short-lived branches (< 24 hours)

Key Principles

๐Ÿ”„ Commit Frequently

Multiple times per day to trunk. Small, incremental changes.

โฑ๏ธ Short-Lived Branches

Feature branches live less than 1 day. Merge quickly.

๐Ÿšฉ Feature Flags

Hide incomplete features behind flags. Enable gradually.

๐Ÿงช Comprehensive Testing

Automated tests catch issues immediately.

Feature Flags Example

// Feature flag controls visibility
if (featureFlags.newCheckout) {
  return <NewCheckout />;  // New feature (hidden)
}
return <OldCheckout />;    // Current production

// Gradual rollout: 1% โ†’ 10% โ†’ 50% โ†’ 100%
// Bug found? Disable flag instantly (no rollback needed)

Pros & Cons

โœ… ProsโŒ Cons
Minimal merge conflictsRequires mature CI/CD
Fastest feedback loopNeeds feature flags infrastructure
Continuous integrationRequires high test coverage
No branch management overheadSteep learning curve
Proven at scale (Google, Meta)Not suitable for all teams

๐Ÿข Real-World Scenarios

When does each strategy work best? Let's look at concrete examples.

๐Ÿ“ฑ

Mobile Banking App โ†’ GitFlow

Traditional bank releasing mobile app

Team Size 30 developers
Release Cycle Every 2 months
Requirement Regulatory approval
โœ… Why GitFlow Works:
  • Scheduled releases with version numbers (v2.1, v2.2)
  • Long QA cycles before release
  • Hotfix capability for production emergencies
  • Release branch allows "feature freeze" for testing
โŒ Why Others Fail:
  • GitHub Flow: Can't do 2-month QA cycles, no version support
  • Trunk-Based: Regulators need to approve releases
๐ŸŒ

SaaS Web Dashboard โ†’ GitHub Flow

Startup building analytics dashboard

Team Size 8 developers
Release Cycle Multiple/day
Requirement Fast iteration
โœ… Why GitHub Flow Works:
  • Simple workflow, minimal overhead
  • Deploy immediately when ready
  • Bug found? Fix, PR, merge, deployed in hours
  • No version numbers needed (it's a website!)
โŒ Why Others Fail:
  • GitFlow: Overkill for a simple web app, slows deployment
  • Trunk-Based: Adds complexity team doesn't need yet
๐Ÿข

Google-Scale Monorepo โ†’ Trunk-Based

Tech giant with thousands of engineers

Team Size 5,000+ devs
Commits/Day 45,000+
Requirement No conflicts
โœ… Why Trunk-Based Works:
  • Long-lived branches at this scale = merge conflict nightmare
  • Everyone commits to trunk = always integrated
  • Feature flags control visibility
  • Automated testing catches issues immediately
โŒ Why Others Fail:
  • GitFlow: 5000 developers with long-lived branches = constant conflicts
  • GitHub Flow: Multi-day branches cause integration pain at scale

What Top Companies Use

Google Trunk-Based
Meta Trunk-Based
Netflix Trunk-Based
GitHub GitHub Flow
Shopify GitHub Flow
Atlassian GitFlow

๐Ÿงน Keeping Git History Clean

A clean Git history makes debugging easier, code review faster, and project maintenance simpler.

Why Clean History Matters

๐Ÿ” Debugging

git bisect works better on linear history to find bug-introducing commits.

๐Ÿ‘€ Code Review

Reviewers see logical, focused commits instead of noise.

๐Ÿ“– Documentation

History tells the story of the project.

โ†ฉ๏ธ Reverts

Can revert single commits cleanly without side effects.

Messy vs Clean History

โŒ MESSY HISTORY (Without Rebase)

*   e5f6g7h Merge branch 'feature-B'
|\
| * a1b2c3d Add feature B part 3
| * d4e5f6g Add feature B part 2
* |   h7i8j9k Merge branch 'feature-A'
|\ \
| * | l0m1n2o Add feature A part 2
| * | p3q4r5s Add feature A part 1
| |/
* | t6u7v8w Fix typo in readme
|/
* b2c3d4e Initial commit

๐Ÿ‘† Hard to follow! Multiple merge commits, crossing lines...

โœ… CLEAN HISTORY (With Rebase)

* e5f6g7h Add feature B part 3
* a1b2c3d Add feature B part 2
* d4e5f6g Add feature B part 1
* h7i8j9k Add feature A part 2
* l0m1n2o Add feature A part 1
* p3q4r5s Fix typo in readme
* b2c3d4e Initial commit

๐Ÿ‘† Linear, easy to read, tells a clear story!

Tools for Clean History

ToolPurpose
git rebaseMove commits to new base, linearize history
git rebase -iEdit, squash, reorder, drop commits
git commit --amendFix the last commit
git resetUndo commits (various modes)

๐Ÿ”„ Rebase in Detail

Rebase means "re-apply your commits on top of another branch" - moving your branch to start from a different point.

Merge vs Rebase

BEFORE (Divergent History):

      Cโ”€โ”€โ”€Dโ”€โ”€โ”€E  (feature)
     /
Aโ”€โ”€โ”€Bโ”€โ”€โ”€Fโ”€โ”€โ”€G  (main)


AFTER MERGE:

      Cโ”€โ”€โ”€Dโ”€โ”€โ”€Eโ”€โ”€โ”€M  (feature)
     /           /
Aโ”€โ”€โ”€Bโ”€โ”€โ”€Fโ”€โ”€โ”€Gโ”€โ”€โ”€โ”€  (main)
              โ†‘
         Merge commit (creates extra commit)


AFTER REBASE:

Aโ”€โ”€โ”€Bโ”€โ”€โ”€Fโ”€โ”€โ”€Gโ”€โ”€โ”€C'โ”€โ”€โ”€D'โ”€โ”€โ”€E'  (feature)
            โ†‘
          main

Your commits replayed on top of main (linear!)

How Rebase Works Step-by-Step

  1. Git identifies common ancestor (B)
  2. Git saves your commits (C, D, E) temporarily
  3. Git moves feature to new base (G)
  4. Git replays each commit one by one:
    • Replay C on G โ†’ C'
    • Replay D on C' โ†’ D'
    • Replay E on D' โ†’ E'
โš ๏ธ Important: C', D', E' are NEW commits with NEW SHA hashes. Same changes, different parents.

Rebase Commands

# Rebase current branch onto main
git rebase main

# Rebase with remote tracking branch
git fetch origin
git rebase origin/main

# Continue after resolving conflicts
git rebase --continue

# Abort rebase (go back to before)
git rebase --abort

# Skip problematic commit
git rebase --skip

The Golden Rule

๐Ÿšจ NEVER REBASE COMMITS THAT OTHERS HAVE PULLED

Rebase rewrites history. If others have your old commits, they'll have conflicts!

โœ… Safe to RebaseโŒ Don't Rebase
Your local commits (not pushed)Shared branches (main, develop)
Your feature branch (only you working)Branches others have pulled
Before creating Pull RequestAfter others are building on your commits

Force Push After Rebase

# After rebasing a pushed branch, you must force push
git push --force-with-lease

# --force-with-lease is SAFER than --force
# It fails if remote has new commits you haven't seen
# Protects against overwriting teammate's work
๐Ÿ’ก If your branch is pushed but NOT shared and NO ONE else is working on it - you can safely rebase and force push. The rule is about not rebasing commits that others have pulled.

๐Ÿ“ฆ Interactive Rebase & Squashing

Interactive rebase lets you edit, reorder, squash, or drop commits before sharing.

# Interactive rebase last 4 commits
git rebase -i HEAD~4

# Interactive rebase all commits since branching from main
git rebase -i main

Interactive Rebase Options

CommandAction
pickUse commit as-is
rewordUse commit, but edit the message
editUse commit, but stop for amending
squashMeld into previous commit (keep message)
fixupMeld into previous commit (discard message)
dropRemove commit entirely

Example: Cleaning Up Before PR

BEFORE (messy commits):
* jkl3456 Add validation
* ghi9012 WIP: debugging
* def5678 Fix typo
* abc1234 Add login form

RUN: git rebase -i HEAD~4

Edit the file:
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
pick abc1234 Add login form
fixup def5678 Fix typo        โ† merge into above
drop ghi9012 WIP: debugging   โ† delete this
squash jkl3456 Add validation โ† merge with message
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

AFTER (clean history):
* xyz9999 Add login form with validation
         (One clean, logical commit!)

Squash Merge in GitHub/GitLab

Many teams use "Squash and Merge" when merging PRs:

โœ… Pros

  • Main branch has clean, logical commits
  • Each PR = one commit
  • Easy to revert entire features

โŒ Cons

  • Loses granular commit history
  • Can't cherry-pick individual changes later

๐Ÿ“ Conventional Commits

A specification for adding human and machine-readable meaning to commit messages.

Format

<type>(<scope>): <description>

[optional body]

[optional footer(s)]

Types

TypeDescription
featNew feature
fixBug fix
docsDocumentation only
styleFormatting, no code change
refactorCode restructuring
testAdding/fixing tests
choreMaintenance tasks
perfPerformance improvement

Examples

# Feature
feat(auth): add OAuth2 login support

# Bug fix
fix(api): handle null response from server

# Documentation
docs(readme): update installation instructions

# Breaking change (note the !)
feat(api)!: change response format to JSON

BREAKING CHANGE: response is now JSON instead of XML

โœ… Best Practices

๐Ÿ“ Commits

  • โœ… Write meaningful commit messages
  • โœ… Commit early, commit often
  • โœ… One logical change per commit
  • โœ… Use conventional commits format
  • โŒ Don't commit broken code
  • โŒ Don't use vague messages

๐ŸŒฟ Branches

  • โœ… Use descriptive names (feature/add-login)
  • โœ… Keep branches short-lived
  • โœ… Delete merged branches
  • โœ… Pull from main frequently
  • โŒ Don't let branches get stale
  • โŒ Don't work directly on main

๐Ÿ”€ Pull Requests

  • โœ… Keep PRs small and focused
  • โœ… Write good PR descriptions
  • โœ… Request reviews early
  • โœ… Address comments promptly
  • โŒ Don't create huge PRs (1000+ lines)
  • โŒ Don't mix features in one PR

๐Ÿ“œ History

  • โœ… Rebase before sharing
  • โœ… Use merge for integrating to main
  • โœ… Squash WIP commits before PR
  • โŒ Don't rewrite shared history
  • โŒ Don't force push to main
  • โŒ Don't keep "WIP" commits in main

๐ŸŽฏ Strategy Selection Guide

Quick Decision Guide

Do you have scheduled releases with version numbers?
โ”œโ”€โ”€ YES โ†’ Do you need to support multiple versions?
โ”‚         โ”œโ”€โ”€ YES โ†’ GitFlow
โ”‚         โ””โ”€โ”€ NO  โ†’ GitLab Flow
โ”‚
โ””โ”€โ”€ NO  โ†’ How often do you deploy?
          โ”œโ”€โ”€ Daily or more โ†’ Team size?
          โ”‚                   โ”œโ”€โ”€ < 50  โ†’ GitHub Flow
          โ”‚                   โ””โ”€โ”€ > 50  โ†’ Trunk-Based
          โ”‚
          โ””โ”€โ”€ Weekly/Monthly โ†’ GitLab Flow

Do you have external contributors?
โ”œโ”€โ”€ YES โ†’ Forking Workflow (+ internal strategy)
โ””โ”€โ”€ NO  โ†’ Use internal strategy only

Quick Reference

ScenarioBest Strategy
Mobile app with App Store releasesGitFlow
SaaS web applicationGitHub Flow
Large team (50+ developers)Trunk-Based
Multiple deployment environmentsGitLab Flow
Open source with external contributorsForking
Startup, small team, fast iterationGitHub Flow
Enterprise with complianceGitFlow / GitLab Flow
Monorepo at scaleTrunk-Based

๐Ÿ“Œ Summary

1. Choose Right Strategy

Based on team size, release cycle, and project type.

2. Keep History Clean

Use rebase, squash, and interactive rebase.

3. Follow Conventions

Consistent commit messages and branch names.

4. Rebase Safely

Only on commits that haven't been shared.

๐Ÿ’ก Remember: The best strategy is the one your team can follow consistently. Start simple (GitHub Flow) and add complexity only when needed.