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
- Parallel development: Develop multiple features simultaneously
- Risk isolation: Isolate unstable code from the mainline
- Code review: Quality assurance through pull requests
- Release management: Control deployment to production
Comparison of Major Branch Strategies
| Strategy | Complexity | Suitable Teams | Deploy Frequency |
|---|---|---|---|
| Feature Branch | Low | Small teams | Varies |
| GitHub Flow | Low | Continuous deployment | Daily to several times/week |
| Git Flow | High | Clear release cycles | Weekly to monthly |
| Trunk Based | Medium | Large, mature teams | Daily 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
- Appropriate size: Aim for 200-400 lines
- Single purpose: One feature/fix per PR
- Detailed description: Include background, changes, and how to test
- 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
| Branch | Purpose | Branches From | Merges To |
|---|---|---|---|
| main | Production releases | - | - |
| develop | Development integration | main | main, release |
| feature/* | Feature development | develop | develop |
| release/* | Release preparation | develop | main, develop |
| hotfix/* | Emergency fixes | main | main, 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
- main branch is always deployable
- Feature development branches from main
- Push to remote regularly
- Code review via pull request
- Merge to main after review
- 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?
| Scenario | Recommended | Reason |
|---|---|---|
| Integration to shared branch | Merge | Preserves history, safe |
| Organizing local commits | Rebase | Clean history |
| Incorporate latest main into feature | Rebase | Linear history |
| Already pushed commits | Merge only | Rewriting 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
- Merge/rebase main frequently: Keep conflicts small
- Communicate: Consult beforehand when editing same files
- Use tools: VS Code, GitKraken, and other GUI tools
- 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
-
Do you deploy continuously?
- Yes → GitHub Flow or Trunk Based
- No → Consider Git Flow
-
What is your release cycle?
- Daily to several times/week → GitHub Flow
- Weekly to monthly → Git Flow
- Multiple times per day → Trunk Based
-
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
Reference Links
Official Documentation & Source
- A successful Git branching model - Vincent Driessen’s original article
- GitHub Flow - GitHub official documentation
- Trunk Based Development - Detailed TBD explanation
Tools
- git-flow - Git extension for Git Flow
- GitHub CLI - Manage PRs from command line
Related Articles & Books
- Atlassian Git Tutorials - Branching - Comparison of various workflows
- Pro Git Book - Branching - Detailed branch explanation
- Google Engineering Practices - Code review best practices