A solid branching strategy enables teams to work in parallel, maintain stable production code, and release features systematically. Without it, teams face merge conflicts, broken builds, and deployment chaos.
Key Benefit: Branching strategies isolate work, protect production code, and enable continuous delivery.
Understanding Git Branches
A branch is a lightweight movable pointer to a commit. It allows you to diverge from the main line of development and continue work without affecting the main codebase.
# Create a new branch
git branch feature/user-authentication
# Switch to the branch
git checkout feature/user-authentication
# Or do both in one command
git checkout -b feature/user-authentication
# Modern Git (2.23+)
git switch -c feature/user-authentication
# List all branches
git branch -a
# Delete a branch
git branch -d feature/user-authentication
# Force delete (if not merged)
git branch -D feature/user-authentication
Basic Branch Types
Branch Type
Purpose
Naming Convention
Main/Master
Production-ready code
main or master
Develop
Integration branch for features
develop or dev
Feature
New features or enhancements
feature/feature-name
Hotfix
Emergency production fixes
hotfix/issue-description
Release
Prepare for production release
release/v1.0.0
Bugfix
Non-critical bug fixes
bugfix/bug-description
Visualizing Branches
maināāāā
feature/logināā
maināāā merge feature
Essential Git Commands
# Check current branch
git branch --show-current
# See branch history
git log --oneline --graph --all --decorate
# Beautiful visualization
git log --graph --pretty=format:'%C(yellow)%h%Creset -%C(red)%d%Creset %s %C(green)(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
# Push new branch to remote
git push -u origin feature/user-authentication
# Pull latest changes from remote
git pull origin develop
# Fetch all branches
git fetch --all
# Track remote branch
git branch --set-upstream-to=origin/develop develop
Branch Naming Best Practices
Use prefixes: feature/, bugfix/, hotfix/, release/
Be descriptive: feature/add-payment-gateway not feature/update
Use lowercase: feature/user-auth not Feature/User-Auth
Use hyphens: feature/social-login not feature/social_login
Include ticket numbers: feature/JIRA-123-user-profile
Keep it short: Aim for 2-4 words after prefix
Pro Tip: Set up branch naming conventions in your team documentation and enforce them with Git hooks or CI/CD pipelines.
Common Branching Mistakes
Avoid These:
⢠Working directly on main/master
⢠Creating branches from wrong base branch
⢠Using vague branch names (update, fix, test)
⢠Keeping branches alive for months
⢠Not updating branch before merging
⢠Forgetting to delete merged branches
Test Your Knowledge - Lesson 1
1. What is the purpose of a feature branch?
2. Which command creates and switches to a new branch?
3. What is the best naming convention for a feature branch?
Lesson 2: GitFlow Strategy
What is GitFlow?
GitFlow is a branching model designed by Vincent Driessen. It defines a strict branching model for project releases, making it ideal for projects with scheduled releases.
Best For: Projects with scheduled releases, multiple versions in production, and large teams requiring strict process.
Never commit directly, only merge from release/hotfix
develop
Integration branch for next release
Merge completed features here, always deployable to staging
Supporting Branches (Short-lived)
Branch Type
Created From
Merged Into
Lifespan
feature/*
develop
develop
Days to weeks
release/*
develop
main + develop
Hours to days
hotfix/*
main
main + develop
Minutes to hours
GitFlow Workflow - Feature Development
# 1. Start a new feature
git checkout develop
git pull origin develop
git checkout -b feature/payment-integration
# 2. Work on feature (make commits)
git add .
git commit -m "Add payment API integration"
git commit -m "Add payment form UI"
git commit -m "Add payment validation"
# 3. Keep feature branch updated
git checkout develop
git pull origin develop
git checkout feature/payment-integration
git merge develop
# Or use rebase for cleaner history
git rebase develop
# 4. Finish feature (merge to develop)
git checkout develop
git merge --no-ff feature/payment-integration
git push origin develop
# 5. Delete feature branch
git branch -d feature/payment-integration
git push origin --delete feature/payment-integration
The --no-ff Flag: Creates a merge commit even if fast-forward is possible. This preserves feature branch history and makes it easy to revert entire features.
GitFlow Workflow - Release
# 1. Create release branch from develop
git checkout develop
git pull origin develop
git checkout -b release/v1.2.0
# 2. Version bumps and minor fixes only
# Update version in package.json, README, etc.
git commit -m "Bump version to 1.2.0"
git commit -m "Update changelog"
git commit -m "Fix typo in documentation"
# 3. Merge to main (production)
git checkout main
git merge --no-ff release/v1.2.0
git tag -a v1.2.0 -m "Version 1.2.0"
git push origin main --tags
# 4. Merge back to develop (to include release fixes)
git checkout develop
git merge --no-ff release/v1.2.0
git push origin develop
# 5. Delete release branch
git branch -d release/v1.2.0
git push origin --delete release/v1.2.0
GitFlow Workflow - Hotfix
# 1. Create hotfix from main
git checkout main
git pull origin main
git checkout -b hotfix/security-patch
# 2. Fix the critical bug
git commit -m "Fix SQL injection vulnerability"
# 3. Merge to main
git checkout main
git merge --no-ff hotfix/security-patch
git tag -a v1.2.1 -m "Hotfix: Security patch"
git push origin main --tags
# 4. Merge to develop (to include fix in future releases)
git checkout develop
git merge --no-ff hotfix/security-patch
git push origin develop
# 5. Delete hotfix branch
git branch -d hotfix/security-patch
git push origin --delete hotfix/security-patch
GitFlow Advantages
Clear structure: Well-defined branch purposes and workflows
Parallel development: Multiple features can be developed simultaneously
Production stability: Main branch always reflects production
Version control: Easy to maintain multiple versions
Emergency fixes: Hotfix workflow handles urgent production issues
GitFlow Disadvantages
Challenges:
⢠Complex for simple projects or continuous deployment
⢠Long-lived feature branches can cause merge conflicts
⢠Release branches add overhead for frequent releases
⢠Not ideal for web apps with single production version
⢠Requires discipline and clear communication
When to Use GitFlow:
ā Desktop/mobile apps with versioned releases
ā Products supporting multiple versions
ā Scheduled release cycles (monthly, quarterly)
ā Large teams needing strict process
ā Projects requiring extensive QA before release
Test Your Knowledge - Lesson 2
1. In GitFlow, where should feature branches be created from?
2. What is the purpose of the --no-ff flag in git merge?
3. Where should a hotfix branch be merged after fixing a production bug?
Lesson 3: GitHub Flow & Trunk-Based Development
GitHub Flow
GitHub Flow is a lightweight, branch-based workflow perfect for teams practicing continuous deployment. It's simpler than GitFlow and ideal for web applications.
Best For: Web applications, continuous deployment, fast-paced teams, SaaS products.
GitHub Flow Principles
maināāāāāā
featureāāā PR āmerge
GitHub Flow Workflow
Create a branch: Branch off from main with descriptive name
Add commits: Make changes and commit regularly
Open Pull Request: Request feedback and start discussion
Discuss and review: Team reviews code, suggests changes
Deploy for testing: Deploy from PR branch to test environment
Merge to main: Once approved and tested, merge and deploy
# GitHub Flow Workflow
# 1. Always start from updated main
git checkout main
git pull origin main
# 2. Create a branch
git checkout -b add-user-profile-page
# 3. Make changes and commit
git add .
git commit -m "Add user profile page component"
git commit -m "Add profile edit functionality"
git commit -m "Add unit tests for profile page"
# 4. Push branch to GitHub
git push -u origin add-user-profile-page
# 5. Open Pull Request on GitHub
# (Done via GitHub web interface)
# 6. Address review comments
git commit -m "Fix styling issues from review"
git push
# 7. After approval, merge via GitHub
# (Usually done via GitHub UI with "Squash and merge" or "Merge")
# 8. Pull latest main locally
git checkout main
git pull origin main
# 9. Delete local branch
git branch -d add-user-profile-page
GitHub Flow Key Rules
Golden Rules:
⢠Main branch is ALWAYS deployable
⢠Branch names are descriptive
⢠Pull Requests are mandatory (no direct commits to main)
⢠CI/CD runs on every PR
⢠Deploy immediately after merge
⢠Keep branches short-lived (days, not weeks)
Trunk-Based Development
Developers work in short-lived feature branches (or directly on trunk) and merge frequently to a single branch (trunk/main). Emphasizes small, frequent integrations.
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Trunk-Based Development Flow ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
main (trunk) āāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā
ā ā ā ā
feature1 āāāāāāāāāāā ā ā
ā ā
feature2 āāāāāāāāāāāāāāāāāāāāāāā ā
ā
feature3 āāāāāāāāāāāāāāāāāāāāāāāāāāā
⢠Features merged multiple times per day
⢠Branches live for hours to 1-2 days max
⢠Feature flags for incomplete features
Trunk-Based Development Workflow
# Trunk-Based Development
# 1. Pull latest from trunk
git checkout main
git pull origin main
# 2. Create short-lived branch (optional)
git checkout -b quick-fix
# 3. Make small, focused change
git commit -m "Fix button alignment on homepage"
# 4. Push and create PR immediately
git push -u origin quick-fix
# 5. Get quick review and merge (same day)
# Merge via GitHub or:
git checkout main
git pull origin main
git merge quick-fix
git push origin main
# 6. Delete branch immediately
git branch -d quick-fix
git push origin --delete quick-fix
# Alternative: Commit directly to trunk (for very small changes)
git checkout main
git pull origin main
# Make change
git commit -m "Update copyright year"
git push origin main
Feature Flags with Trunk-Based
Use feature flags to merge incomplete features without exposing them to users.
// Example: Feature flag in code
const FEATURES = {
newCheckoutFlow: process.env.FEATURE_NEW_CHECKOUT === 'true'
};
function renderCheckout() {
if (FEATURES.newCheckoutFlow) {
return ; // Work in progress
}
return ; // Stable version
}
// Deploy to production with flag OFF
// Enable flag when feature is complete
// Gradually roll out: 10% users ā 50% ā 100%
// Remove flag and old code after successful rollout
Comparison: GitHub Flow vs Trunk-Based
Aspect
GitHub Flow
Trunk-Based Development
Branch lifespan
Days to 1-2 weeks
Hours to 1-2 days
Merge frequency
Multiple times per week
Multiple times per day
Feature flags
Optional
Essential
Code review
Always via PR
PR or pair programming
CI/CD maturity
Moderate to High
High (required)
Team size
Any size
Works best with small to medium teams
Benefits of Simpler Workflows
Faster delivery: Features reach production quickly
Easier to learn: Simple process for new team members
Always deployable: Main branch is production-ready
Better for CI/CD: Aligns with continuous deployment
Requirements:
⢠Strong CI/CD pipeline with automated tests
⢠Fast test suite (under 10 minutes)
⢠Team discipline and communication
⢠Ability to roll back quickly
⢠Monitoring and alerting in production
Test Your Knowledge - Lesson 3
1. In GitHub Flow, which branch should always be deployable?
2. What is the maximum recommended lifespan for branches in Trunk-Based Development?
3. Why are feature flags important in Trunk-Based Development?
Lesson 4: Release Management & Tagging
Semantic Versioning
Semantic Versioning (SemVer) is a versioning scheme that conveys meaning about the underlying changes. Format: MAJOR.MINOR.PATCH
Version Format: MAJOR.MINOR.PATCH (e.g., 2.4.1)
⢠MAJOR: Breaking changes (incompatible API changes)
⢠MINOR: New features (backward-compatible)
⢠PATCH: Bug fixes (backward-compatible)
Tags are references that point to specific commits. Use them to mark release points (v1.0, v2.0, etc.).
# Create annotated tag (recommended)
git tag -a v1.0.0 -m "Release version 1.0.0"
# Create lightweight tag
git tag v1.0.0
# Tag specific commit
git tag -a v1.0.0 9fceb02 -m "Release version 1.0.0"
# List all tags
git tag
git tag -l "v1.*"
# Show tag information
git show v1.0.0
# Push tag to remote
git push origin v1.0.0
# Push all tags
git push origin --tags
# Delete local tag
git tag -d v1.0.0
# Delete remote tag
git push origin --delete v1.0.0
# Checkout specific tag
git checkout v1.0.0
Release Workflow
# Complete Release Process
# 1. Prepare release
git checkout develop
git pull origin develop
git checkout -b release/v1.5.0
# 2. Update version numbers
# Update package.json, version files, changelogs
git commit -m "Bump version to 1.5.0"
# 3. Run final tests
npm test
npm run build
# 4. Merge to main
git checkout main
git pull origin main
git merge --no-ff release/v1.5.0
# 5. Tag the release
git tag -a v1.5.0 -m "Release version 1.5.0
New Features:
- User authentication
- Password reset
- Email notifications
Bug Fixes:
- Fix login redirect issue
- Fix mobile responsiveness
Breaking Changes:
- API endpoint /api/user changed to /api/users"
# 6. Push to remote
git push origin main
git push origin v1.5.0
# 7. Merge back to develop
git checkout develop
git merge --no-ff release/v1.5.0
git push origin develop
# 8. Clean up
git branch -d release/v1.5.0
# 9. Create GitHub Release
# Go to GitHub ā Releases ā Draft new release
# Select tag, add release notes, attach binaries if needed
Changelog Management
Keep a CHANGELOG.md file to track all notable changes in each version.
# CHANGELOG.md
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).
## [Unreleased]
### Added
- New feature in development
## [1.5.0] - 2024-03-15
### Added
- User authentication system
- Password reset functionality
- Email notification service
### Changed
- Updated API endpoint structure
- Improved error handling
### Fixed
- Login redirect issue
- Mobile responsiveness on profile page
### Security
- Fixed SQL injection vulnerability
## [1.4.2] - 2024-02-28
### Fixed
- Critical bug in payment processing
- Memory leak in image upload
## [1.4.1] - 2024-02-20
### Fixed
- Minor UI glitches
- Typos in error messages
Before Every Release:
ā All tests passing
ā Code reviewed and approved
ā Version numbers updated
ā Changelog updated
ā Documentation updated
ā Database migrations tested
ā Deployment scripts verified
ā Rollback plan prepared
ā Stakeholders notified
ā Monitoring alerts configured
Common Release Mistakes:
⢠Forgetting to update version numbers
⢠Not testing on production-like environment
⢠Missing database migrations
⢠No rollback plan
⢠Poor communication with team
⢠Releasing on Friday afternoon
Test Your Knowledge - Lesson 4
1. In Semantic Versioning (1.2.3), what does the "2" represent?
2. What command creates an annotated Git tag?
3. Which file is commonly used to track version changes?
Lesson 5: Merge Strategies & Conflict Resolution
Git Merge Strategies
Understanding different merge strategies helps you maintain clean history and resolve conflicts effectively.
1. Merge Commit (Default)
# Creates a merge commit
git checkout main
git merge feature-branch
# With --no-ff (no fast-forward)
git merge --no-ff feature-branch
# Pros:
# ā Preserves complete history
# ā Shows when feature was integrated
# ā Easy to revert entire feature
# Cons:
# ā Creates merge commits (can clutter history)
# ā Non-linear history
2. Fast-Forward Merge
# Fast-forward (if possible)
git checkout main
git merge feature-branch
# Force fast-forward (fails if not possible)
git merge --ff-only feature-branch
# Pros:
# ā Linear history
# ā No merge commits
# ā Clean, simple history
# Cons:
# ā Loses information about feature branches
# ā Harder to revert features
3. Rebase
# Rebase feature onto main
git checkout feature-branch
git rebase main
# Interactive rebase (squash, reorder, edit commits)
git rebase -i main
# After rebase, force push (if already pushed)
git push --force-with-lease
# Pros:
# ā Linear, clean history
# ā No merge commits
# ā Easy to follow
# Cons:
# ā Rewrites history (dangerous on shared branches)
# ā Can be confusing for beginners
# ā Loses merge context
ā ļø Golden Rule of Rebasing:
Never rebase commits that have been pushed to a shared/public branch!
Only rebase local commits or your own feature branches.
4. Squash and Merge
# Squash all commits into one
git checkout main
git merge --squash feature-branch
git commit -m "Add user authentication feature"
# Or via GitHub UI: "Squash and merge" button
# Pros:
# ā Clean, linear history
# ā One commit per feature
# ā Easy to revert
# Cons:
# ā Loses individual commit history
# ā Makes it harder to find specific changes
Merge Strategy Comparison
Strategy
History
Use Case
Revert
Merge Commit
Non-linear
GitFlow, preserving context
Easy (revert merge)
Fast-Forward
Linear
Small changes, simple workflows
Hard (revert individual commits)
Rebase
Linear
Feature branches, clean history
Hard (commits rewritten)
Squash
Linear
GitHub Flow, one feature = one commit
Easy (revert single commit)
Handling Merge Conflicts
Conflicts occur when Git can't automatically merge changes. Here's how to resolve them:
# Attempt merge
git merge feature-branch
# Output: CONFLICT (content): Merge conflict in file.js
# 1. Check status
git status
# Shows: both modified: file.js
# 2. Open conflicted file
# You'll see conflict markers:
<<<<<<< HEAD
current branch code
=======
incoming branch code
>>>>>>> feature-branch
# 3. Resolve conflict manually
# Edit file to desired state, remove markers
# 4. Mark as resolved
git add file.js
# 5. Complete merge
git commit -m "Merge feature-branch, resolve conflicts in file.js"
# Or abort merge
git merge --abort
Conflict Resolution Tools
# Use merge tool
git mergetool
# Configure merge tool (VS Code)
git config --global merge.tool vscode
git config --global mergetool.vscode.cmd 'code --wait $MERGED'
# Other popular merge tools:
# - Beyond Compare
# - KDiff3
# - P4Merge
# - Meld
# View conflicts in diff format
git diff
# Accept all changes from one side
git checkout --ours file.js # Keep current branch
git checkout --theirs file.js # Take incoming branch
Preventing Merge Conflicts
Merge frequently: Sync with main/develop daily
Keep branches small: Short-lived branches have fewer conflicts
Communicate: Coordinate when working on same files
Pull before push: Always pull latest changes first
Use Merge When:
ā Working on public/shared branches
ā Need to preserve exact history
ā Following GitFlow
ā Want to see when features were integrated
Use Rebase When:
ā Cleaning up local commits before pushing
ā Want linear history
ā Updating feature branch with latest main
ā Working on your own feature branch
Interactive Rebase Example
# Clean up last 3 commits
git rebase -i HEAD~3
# Interactive menu:
pick abc1234 Add login form
pick def5678 Fix typo
pick ghi9012 Update styles
# Change to:
pick abc1234 Add login form
squash def5678 Fix typo
squash ghi9012 Update styles
# Result: One clean commit with all changes
# Other rebase commands:
# pick - keep commit
# reword - change commit message
# edit - stop to amend commit
# squash - combine with previous
# fixup - like squash but discard message
# drop - remove commit
Test Your Knowledge - Lesson 5
1. What is the golden rule of rebasing?
2. What does "Squash and merge" do?
3. How do you abort a merge that has conflicts?
Lesson 6: Best Practices & Team Workflows
Commit Best Practices
Good commits are the foundation of effective version control and collaboration.
Writing Good Commit Messages
# Conventional Commits Format
():
Atomic Commits
Atomic Commit Principle: Each commit should be a single, complete unit of change.
ā Makes code review easier
ā Simplifies reverting changes
ā Improves git bisect effectiveness
ā Creates clear project history
# Bad: Multiple unrelated changes in one commit
git add authentication.js payment.js homepage.css
git commit -m "various updates"
# Good: Separate commits for separate concerns
git add authentication.js
git commit -m "feat(auth): add two-factor authentication"
git add payment.js
git commit -m "fix(payment): resolve Stripe webhook timeout"
git add homepage.css
git commit -m "style(home): update hero section layout"
# Stage parts of a file
git add -p filename.js
Branch Protection Rules
Protect important branches from accidental or malicious changes.
# GitHub Branch Protection Rules (via Settings > Branches)
ā Require pull request reviews before merging
- Number of required approvals: 2
- Dismiss stale reviews when new commits are pushed
- Require review from Code Owners
ā Require status checks to pass before merging
- Require branches to be up to date
- Status checks: CI/CD, tests, linting
ā Require conversation resolution before merging
ā Require signed commits
ā Include administrators (enforce rules on admins too)
ā Restrict who can push to matching branches
ā Allow force pushes: Never
ā Allow deletions: Never
Pull Request Best Practices
Practice
Description
Benefit
Small PRs
Under 400 lines changed
Faster reviews, fewer bugs
Descriptive titles
Clear summary of changes
Easy to understand at a glance
Complete description
Context, testing, screenshots
Reviewers understand the why
Link issues
Reference related tickets
Traceability
Self-review first
Review your own code before requesting
Catch obvious issues
Request specific reviewers
Tag domain experts
Better quality reviews
PR Template Example
# .github/pull_request_template.md
## Description
Brief summary of changes
## Type of Change
- [ ] Bug fix (non-breaking change)
- [ ] New feature (non-breaking change)
- [ ] Breaking change
- [ ] Documentation update
## Related Issues
Fixes #(issue number)
## How Has This Been Tested?
- [ ] Unit tests
- [ ] Integration tests
- [ ] Manual testing
## Checklist
- [ ] My code follows the project style guidelines
- [ ] I have performed a self-review
- [ ] I have commented my code where necessary
- [ ] I have updated the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix/feature works
- [ ] New and existing tests pass locally
- [ ] Any dependent changes have been merged
## Screenshots (if applicable)
[Add screenshots here]
Code Review Guidelines
As a Reviewer:
ā Be constructive and kind
ā Ask questions, don't demand
ā Explain the "why" behind suggestions
ā Praise good solutions
ā Distinguish between blocking and non-blocking comments
ā Review within 24 hours
ā Focus on code, not the person
As a PR Author:
ā Respond to all comments
ā Don't take feedback personally
ā Ask for clarification if needed
ā Mark conversations as resolved
ā Thank reviewers
ā Update PR based on feedback
Git Hooks for Automation
# .git/hooks/pre-commit
#!/bin/bash
# Run linter before commit
npm run lint
if [ $? -ne 0 ]; then
echo "ā Linting failed. Please fix errors before committing."
exit 1
fi
npm test
if [ $? -ne 0 ]; then
echo "ā Tests failed. Please fix tests before committing."
exit 1
fi
echo "ā Pre-commit checks passed!"
# Make executable
chmod +x .git/hooks/pre-commit
# Use Husky for easier hook management
npm install --save-dev husky
npx husky install
npx husky add .git/hooks/pre-commit "npm run lint && npm test"
Team Workflow Example
# Complete Team Workflow
# 1. Pick up ticket from board (Jira, GitHub Issues)
# Status: To Do ā In Progress
# 2. Create feature branch
git checkout main
git pull origin main
git checkout -b feature/JIRA-123-user-dashboard
# 3. Make changes with atomic commits
git commit -m "feat(dashboard): add dashboard layout"
git commit -m "feat(dashboard): add user stats widget"
git commit -m "test(dashboard): add dashboard component tests"
# 4. Keep branch updated
git fetch origin main
git rebase origin/main
# 5. Push to remote
git push -u origin feature/JIRA-123-user-dashboard
# 6. Create Pull Request on GitHub
# - Add description
# - Link to JIRA-123
# - Request 2 reviewers
# - Add labels
# 7. Address review comments
git commit -m "refactor(dashboard): extract stats logic per review"
git push
# 8. Merge after approval
# Use "Squash and merge" on GitHub
# 9. Delete branch
git checkout main
git pull origin main
git branch -d feature/JIRA-123-user-dashboard
# 10. Update ticket status
# Status: In Review ā Done
Final Tips for Success:
⢠Document your team's workflow in README
⢠Automate everything possible (hooks, CI/CD)
⢠Review and improve workflow regularly
⢠Prioritize communication over process
⢠Keep it simple - don't over-engineer
⢠Train new team members thoroughly
⢠Use visual tools (GitKraken, SourceTree) if helpful
Test Your Knowledge - Lesson 6
1. What is an atomic commit?
2. What is the recommended maximum lines changed in a Pull Request?