Git Storytelling - Branch Strategy
This skill helps you implement effective branching strategies that tell the story of your development process through organized, purposeful branch management. Good branching creates a clear narrative of parallel development efforts.
Core Concepts
Why Branch Strategy Matters
A good branching strategy:
-
Creates clear development narratives - Each branch tells a specific story
-
Enables parallel work - Multiple features can develop simultaneously
-
Facilitates code review - Changes are isolated and reviewable
-
Supports deployment workflows - Different branches for different environments
-
Reduces merge conflicts - Smaller, focused branches are easier to merge
-
Documents development history - Branch names and structure show intent
The Story of Branches
Think of branches as parallel storylines in your codebase:
-
Main branch: The canonical story, always working and deployable
-
Feature branches: Side quests that eventually merge into the main story
-
Release branches: Chapters being prepared for publication
-
Hotfix branches: Emergency patches to the published story
-
Development branch: The staging area where stories come together
Branch Naming Conventions
Standard Prefixes
Use consistent prefixes to categorize branches:
feature/ - New features fix/ - Bug fixes hotfix/ - Production emergency fixes refactor/ - Code refactoring test/ - Testing changes docs/ - Documentation chore/ - Maintenance tasks release/ - Release preparation
Naming Best Practices
Good branch names are:
GOOD: Clear, descriptive, kebab-case
feature/user-authentication fix/payment-processing-timeout refactor/extract-validation-logic hotfix/critical-security-patch
BAD: Vague, unclear, inconsistent
feature/new-stuff fix-thing my-branch temp
Including Issue Numbers
Reference tracking system issues:
feature/123-add-user-authentication fix/456-resolve-memory-leak hotfix/789-patch-security-vulnerability
Branch Name Format
Follow a consistent pattern:
<type>/<issue-number>-<short-description>
Examples: feature/234-oauth-integration fix/567-null-pointer-exception refactor/890-simplify-error-handling
Common Branching Strategies
Git Flow
A robust branching model for release-based software:
Main branches (permanent)
main # Production-ready code develop # Integration branch for features
Supporting branches (temporary)
feature/* # New features release/* # Release preparation hotfix/* # Production fixes
Git Flow Workflow:
Start new feature
git checkout develop git checkout -b feature/user-profile
Work on feature with commits
git commit -m "feat: add user profile model" git commit -m "feat: add profile update endpoint"
Finish feature
git checkout develop git merge --no-ff feature/user-profile git branch -d feature/user-profile
Start release
git checkout develop git checkout -b release/v1.2.0
Prepare release
git commit -m "chore: bump version to 1.2.0" git commit -m "docs: update CHANGELOG"
Finish release
git checkout main git merge --no-ff release/v1.2.0 git tag -a v1.2.0 -m "Release version 1.2.0" git checkout develop git merge --no-ff release/v1.2.0 git branch -d release/v1.2.0
Emergency hotfix
git checkout main git checkout -b hotfix/v1.2.1
Fix and release
git commit -m "fix: critical security issue" git checkout main git merge --no-ff hotfix/v1.2.1 git tag -a v1.2.1 -m "Hotfix version 1.2.1" git checkout develop git merge --no-ff hotfix/v1.2.1 git branch -d hotfix/v1.2.1
GitHub Flow
A simpler model for continuous deployment:
Only one main branch
main # Always deployable
All work in feature branches
feature/* # Features, fixes, everything
GitHub Flow Workflow:
Create feature branch from main
git checkout main git pull origin main git checkout -b feature/add-search
Make commits
git commit -m "feat: add search component" git commit -m "test: add search tests" git commit -m "docs: document search API"
Push and create pull request
git push -u origin feature/add-search
After review and CI passes, merge via PR
Then deploy main branch
Clean up
git checkout main git pull origin main git branch -d feature/add-search
Trunk-Based Development
Minimal branching with short-lived feature branches:
Main branch
main # The trunk, always deployable
Short-lived feature branches (< 1 day)
feature/* # Small, quick features
Trunk-Based Workflow:
Create short-lived feature branch
git checkout main git pull origin main git checkout -b feature/update-button-text
Make focused change
git commit -m "feat: update CTA button text"
Push and merge same day
git push -u origin feature/update-button-text
Merge via PR or direct merge
git checkout main git merge feature/update-button-text git push origin main
Delete branch immediately
git branch -d feature/update-button-text
GitLab Flow
Environment branches for deployment stages:
Main development branch
main # Integration branch
Environment branches
staging # Staging environment production # Production environment
Feature branches
feature/* # Features merge to main
GitLab Flow Workflow:
Develop feature
git checkout main git checkout -b feature/notification-system git commit -m "feat: add notification system"
Merge to main
git checkout main git merge feature/notification-system
Deploy to staging
git checkout staging git merge main git push origin staging # Triggers staging deployment
After testing, deploy to production
git checkout production git merge staging git push origin production # Triggers production deployment
Code Examples
Example 1: Starting a Feature Branch
Update main branch
git checkout main git pull origin main
Create feature branch with descriptive name
git checkout -b feature/456-implement-two-factor-auth
Verify you're on new branch
git branch --show-current
Output: feature/456-implement-two-factor-auth
Make initial commit
git commit --allow-empty -m "feat: initialize two-factor authentication feature"
Push branch to remote
git push -u origin feature/456-implement-two-factor-auth
Continue development
git commit -m "feat: add TOTP token generation" git commit -m "feat: add token verification endpoint" git commit -m "test: add 2FA integration tests"
Example 2: Keeping Feature Branch Updated
While working on feature branch, main has moved forward
git checkout feature/789-user-dashboard
Option 1: Rebase (creates linear history)
git fetch origin git rebase origin/main
If conflicts occur
git status # See conflicting files
Fix conflicts in editor
git add . git rebase --continue
Option 2: Merge (preserves branch history)
git fetch origin git merge origin/main
Resolve any merge conflicts
git add . git commit -m "merge: resolve conflicts with main"
Push updated branch
git push --force-with-lease origin feature/789-user-dashboard
Example 3: Release Branch Workflow
Create release branch from develop
git checkout develop git pull origin develop git checkout -b release/v2.0.0
Prepare release
git commit -m "chore: bump version to 2.0.0" git commit -m "docs: update CHANGELOG for v2.0.0" git commit -m "chore: update dependencies"
Fix bugs found during release testing
git commit -m "fix: resolve edge case in user validation" git commit -m "fix: correct API response format"
Merge to main and tag
git checkout main git merge --no-ff release/v2.0.0 git tag -a v2.0.0 -m "Release version 2.0.0
Major changes:
- New user authentication system
- Improved performance
- Updated API endpoints
See CHANGELOG.md for details."
Merge back to develop
git checkout develop git merge --no-ff release/v2.0.0
Push everything
git push origin main git push origin develop git push origin v2.0.0
Clean up
git branch -d release/v2.0.0
Example 4: Emergency Hotfix
Production is broken, need immediate fix
git checkout main git pull origin main
Create hotfix branch
git checkout -b hotfix/critical-login-bug
Make the fix
git commit -m "fix: resolve null pointer in login handler
Users unable to log in when email field contains trailing whitespace. Add trim() to email input processing.
Critical production issue affecting 15% of login attempts.
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>"
Test the fix
npm test
Merge to main
git checkout main git merge --no-ff hotfix/critical-login-bug git tag -a v1.5.1 -m "Hotfix: Login bug fix"
Deploy immediately
git push origin main git push origin v1.5.1
Merge to develop so fix isn't lost
git checkout develop git merge --no-ff hotfix/critical-login-bug git push origin develop
Clean up
git branch -d hotfix/critical-login-bug git push origin --delete hotfix/critical-login-bug
Example 5: Collaborative Feature Branch
Developer A starts feature
git checkout -b feature/payment-integration git commit -m "feat: add payment gateway client" git push -u origin feature/payment-integration
Developer B joins the work
git fetch origin git checkout feature/payment-integration
Developer B makes changes
git commit -m "feat: add webhook handler" git pull --rebase origin feature/payment-integration git push origin feature/payment-integration
Developer A pulls updates
git checkout feature/payment-integration git pull --rebase origin feature/payment-integration
Continue collaborating until complete
git commit -m "test: add payment integration tests" git commit -m "docs: document payment webhook API"
Create pull request for review
git push origin feature/payment-integration
Example 6: Experimental Branch
Trying a risky approach
git checkout -b experiment/new-architecture
Make experimental commits
git commit -m "experiment: try event-driven architecture" git commit -m "experiment: add message queue integration"
Test the approach
npm test npm run benchmark
Decision 1: Experiment failed, abandon it
git checkout main git branch -D experiment/new-architecture
Decision 2: Experiment succeeded, integrate it
git checkout -b feature/event-driven-refactor git merge experiment/new-architecture git commit -m "refactor: migrate to event-driven architecture" git push -u origin feature/event-driven-refactor
Clean up experiment branch
git branch -d experiment/new-architecture
Example 7: Stacked Branches
Large feature requires multiple PRs
git checkout main
First part: Database schema
git checkout -b feature/schema-updates git commit -m "feat: add new database tables" git commit -m "feat: add migration scripts" git push -u origin feature/schema-updates
Second part: API (depends on schema)
git checkout -b feature/api-endpoints git commit -m "feat: add user API endpoints" git commit -m "test: add API integration tests" git push -u origin feature/api-endpoints
Third part: UI (depends on API)
git checkout -b feature/user-interface git commit -m "feat: add user management UI" git commit -m "test: add UI component tests" git push -u origin feature/user-interface
Merge order: schema -> API -> UI
As each PR is approved and merged, rebase next branch onto main
Example 8: Branch Cleanup
List all branches
git branch -a
Delete local branches that are merged
git branch --merged main | grep -v "main" | xargs git branch -d
Delete remote branch
git push origin --delete feature/old-feature
Prune remote tracking branches
git fetch --prune
Delete local branches that no longer exist on remote
git remote prune origin
Interactive cleanup
git branch -vv | grep ': gone]' | awk '{print $1}' | xargs git branch -D
See stale branches
git for-each-ref --sort=-committerdate refs/heads/
--format='%(committerdate:short) %(refname:short)'
When to Use This Skill
Use this skill when:
-
Starting a new project and establishing branching conventions
-
Planning feature development across multiple developers
-
Setting up CI/CD pipelines with branch-based deployments
-
Coordinating release schedules and version management
-
Managing hotfixes to production environments
-
Onboarding new team members to git workflow
-
Resolving complex merge situations
-
Refactoring large portions of codebase
-
Experimenting with architectural changes
-
Maintaining multiple versions of software simultaneously
Best Practices
Keep branches short-lived - Merge within days, not weeks, to reduce merge conflicts
Use descriptive branch names - Future you will thank present you
Delete merged branches - Keep repository clean and navigable
One purpose per branch - Don't mix features, fixes, and refactoring
Update from main regularly - Frequent rebasing/merging reduces conflict pain
Protect main branch - Require PR reviews, passing tests before merge
Use branch prefixes consistently - Enables automation and filtering
Include issue numbers - Creates traceability to requirements
Push branches early - Enables collaboration and provides backup
Create PR early as draft - Get early feedback on approach
Review changes before creating PR - Use git diff main...HEAD
Write meaningful merge commits - Explain what the branch accomplished
Tag releases - Mark important points in history
Document branching strategy - In README or CONTRIBUTING guide
Automate branch cleanup - Use tools to delete stale branches
Common Pitfalls
Long-lived branches - Weeks-old branches become nightmare to merge
Inconsistent naming - Mix of conventions confuses everyone
Working directly on main - Bypasses review and CI checks
Forgetting to pull before branching - Start from stale base
Creating branches from wrong base - Feature from feature instead of main
Not updating feature branches - Drift from main causes conflicts
Keeping too many local branches - Clutters workspace
Force pushing shared branches - Destroys collaborator's work
Mixing unrelated changes - One branch does too many things
Not cleaning up merged branches - Repository becomes graveyard
Creating nested branch hierarchies - Overly complex dependencies
Merging without testing - Breaks main branch
No branch protection rules - Anyone can push to main
Using generic branch names - "fix" or "update" tells nothing
Forgetting to push branches - Work exists only locally
Resources
Git Commands for Branch Management
Create and switch to new branch
git checkout -b <branch-name> git switch -c <branch-name> # Modern alternative
Switch branches
git checkout <branch-name> git switch <branch-name> # Modern alternative
List branches
git branch # Local branches git branch -r # Remote branches git branch -a # All branches git branch -vv # Verbose with tracking info
Delete branches
git branch -d <branch> # Delete if merged git branch -D <branch> # Force delete git push origin --delete <branch> # Delete remote
Rename branch
git branch -m <old> <new> # Rename local git push origin -u <new> # Push renamed git push origin --delete <old> # Delete old remote
Track remote branch
git branch -u origin/<branch> git checkout --track origin/<branch>
Compare branches
git diff main...feature-branch git log main..feature-branch git log --graph --oneline --all
Merge strategies
git merge <branch> # Regular merge git merge --no-ff <branch> # Force merge commit git merge --squash <branch> # Squash into one commit
Rebase
git rebase main # Rebase onto main git rebase -i main # Interactive rebase git rebase --continue # Continue after conflicts git rebase --abort # Abandon rebase
Cherry-pick
git cherry-pick <commit-hash> # Apply specific commit
Branch Protection Rules
Configure on GitHub/GitLab:
Protected Branch: main
- Require pull request reviews: 2 reviewers
- Require status checks to pass: true
- Tests
- Linting
- Build
- Require branches to be up to date: true
- Include administrators: true
- Restrict push: true
- Allow force pushes: false
- Allow deletions: false
Git Aliases for Branch Management
Add to .gitconfig :
[alias] # Branch management br = branch co = checkout cob = checkout -b
# Branch cleanup
bclean = "!f() { git branch --merged ${1-main} | grep -v " ${1-main}$" | xargs git branch -d; }; f"
# Branch status
bstat = branch -vv
# Recent branches
recent = branch --sort=-committerdate --format='%(committerdate:short) %(refname:short)'
# Current branch name
current = branch --show-current
# Push current branch
pub = "!git push -u origin $(git current)"
# Update branch from main
update = "!git fetch origin && git rebase origin/main"
Visualization Tools
View branch structure
git log --graph --oneline --all --decorate
Detailed branch graph
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all
See all branches with last commit
git branch -v
Branch topology
git show-branch
Visual git tools
gitk --all # Built-in visualizer git gui # Built-in GUI
Related Skills
-
git-storytelling-commit-strategy: When to commit on branches
-
git-storytelling-commit-messages: Writing clear commit messages
-
code-reviewer: How branches facilitate code review
Advanced Patterns
Feature Flags for Trunk-Based Development
Instead of long-lived branches, use feature flags:
// feature-flags.js export const features = { newUserDashboard: process.env.ENABLE_NEW_DASHBOARD === 'true', betaPaymentFlow: process.env.ENABLE_BETA_PAYMENT === 'true', };
// component.jsx import { features } from './feature-flags';
function Dashboard() { if (features.newUserDashboard) { return <NewDashboard />; } return <LegacyDashboard />; }
This allows merging incomplete features to main without exposing them:
Commit partial feature to main
git checkout main git commit -m "feat: add new dashboard (behind feature flag)" git push origin main
Feature is deployed but not active
Enable when ready via environment variable
Branch Strategy Documentation
Document in CONTRIBUTING.md :
Branching Strategy
We use GitHub Flow with the following conventions:
Branch Types
feature/*- New featuresfix/*- Bug fixeshotfix/*- Production emergency fixesrefactor/*- Code improvementsdocs/*- Documentation
Workflow
- Create branch from
main:git checkout -b feature/123-description - Make commits following our commit message guidelines
- Keep branch updated:
git rebase origin/main - Push and create PR:
git push -u origin feature/123-description - After approval and CI passes, merge via PR
- Delete branch after merge
Branch Naming
Format: <type>/<issue>-<description>
Examples:
feature/456-user-authenticationfix/789-memory-leakhotfix/101-critical-security-patch
Branch Lifecycle
- Create branches from up-to-date
main - Keep branches under 3 days old
- Delete immediately after merge
- Never force push to
main
Conclusion
Effective branch strategy is essential for telling a clear development story. By following consistent naming conventions, keeping branches focused and short-lived, and choosing the right branching model for your team's needs, you create a git history that is navigable, understandable, and valuable.
Remember: Branches are temporary workspaces for focused development. Use them to isolate changes, enable parallel work, and facilitate code review. Then merge them and clean them up. A clean branch structure is a sign of a healthy, well-managed codebase.