Working with Branches
Branches are one of Git's most powerful features, enabling parallel development, experimentation, and organized workflows. In this lesson, you'll master branch creation, navigation, management, and best practices.
What Are Branches?
A branch is a lightweight movable pointer to a commit. Think of it as a separate line of development:
Main/Master Branch: The primary branch (production-ready code)
Feature Branches: Isolated development of new features
Bugfix Branches: Fixing specific bugs
Hotfix Branches: Urgent production fixes
Experimental Branches: Testing ideas without risk
Key Fact: Branches in Git are incredibly lightweight - they're just 41-byte files containing a SHA-1 hash. Creating and switching branches is almost instant, even in large repositories!
Why Use Branches?
Benefits:
✓ Isolate work - develop features without affecting main code
✓ Parallel development - multiple team members work simultaneously
✓ Experimentation - try ideas without risk
✓ Context switching - work on multiple tasks easily
✓ Code review - changes reviewed before merging to main
✓ Organized workflow - clear separation of concerns
Creating Branches
Multiple ways to create branches:
# Create a new branch (doesn't switch to it)
git branch feature-login
# Create and switch to new branch
git checkout -b feature-login
# Modern way (Git 2.23+)
git switch -c feature-login
# Create branch from specific commit
git branch bugfix-header abc123
# Create branch from another branch
git branch feature-payment feature-login
# Create branch and track remote
git checkout -b local-name origin/remote-branch
Tip: Use git switch (Git 2.23+) for clarity: git switch switches branches, git checkout does many things. The new command makes your intentions clearer.
Switching Branches
Navigate between branches:
# Switch to existing branch (old way)
git checkout main
# Switch to branch (modern way)
git switch main
# Switch to previous branch
git switch -
# Create and switch to new branch
git switch -c new-feature
# Switch with uncommitted changes (Git stashes automatically)
git switch other-branch # May fail if conflicts exist
Warning: Uncommitted changes in your working directory must be compatible with the target branch. If there are conflicts, Git will prevent the switch. Either commit, stash, or discard changes first.
Listing Branches
View all branches and their status:
# List local branches (* marks current)
git branch
# List all branches (local + remote)
git branch -a
# List remote branches only
git branch -r
# List with last commit on each branch
git branch -v
# List merged branches
git branch --merged
# List unmerged branches
git branch --no-merged
# List branches with more details
git branch -vv # Shows tracking info
Branch Naming Conventions
Use clear, descriptive names that follow your team's conventions:
Common Patterns:
feature/user-authentication
feature/payment-integration
bugfix/header-alignment
bugfix/login-error
hotfix/security-patch
release/v1.2.0
experimental/new-design
Best Practices:
✓ Use lowercase and hyphens
✓ Include type prefix (feature/, bugfix/)
✓ Be descriptive but concise
✓ Use issue numbers: feature/123-user-profile
✓ Avoid special characters and spaces
Examples:
✓ feature/add-shopping-cart
✓ bugfix/fix-checkout-error
✓ hotfix/patch-security-issue
✗ my-branch (too vague)
✗ FEATURE (all caps)
✗ new feature (spaces)
Team Convention: Always follow your team's naming conventions. Consistency is more important than personal preference!
Deleting Branches
Remove branches you no longer need:
# Delete fully merged branch
git branch -d feature-login
# Force delete (even if not merged)
git branch -D experimental-feature
# Delete remote branch
git push origin --delete feature-login
git push origin :feature-login # Older syntax
# Delete multiple branches
git branch -d feature-1 feature-2 feature-3
# Delete all merged branches except main
git branch --merged | grep -v "\*\|main\|master" | xargs git branch -d
Warning: git branch -D force-deletes branches even if they contain unmerged work. Make sure you don't need that work before using the force flag!
Renaming Branches
Change branch names:
# Rename current branch
git branch -m new-name
# Rename another branch
git branch -m old-name new-name
# Rename and update remote
git branch -m old-name new-name
git push origin --delete old-name
git push origin new-name
git push origin -u new-name # Set upstream
Tracking Branches
Connect local branches to remote branches:
# Create branch that tracks remote
git checkout -b local-branch origin/remote-branch
# Set upstream for current branch
git branch -u origin/main
# Push and set upstream tracking
git push -u origin feature-branch
# View tracking information
git branch -vv
# Remove upstream tracking
git branch --unset-upstream
Pro Tip: Always use git push -u origin branch-name when pushing a new branch for the first time. This sets up tracking and allows you to simply use git push and git pull without specifying the remote and branch.
Detached HEAD State
Understanding and working with detached HEAD:
# Checkout specific commit (detached HEAD)
git checkout abc123
# Detached HEAD warning:
# You are in 'detached HEAD' state. You can look around,
# make experimental changes and commit them, and you can
# discard any commits you make in this state.
# Work in detached HEAD
git checkout abc123
# Make changes and commit
git add .
git commit -m "Experimental change"
# Save work from detached HEAD
git branch save-experiment
git switch main
# Or attach HEAD to new branch
git checkout -b new-branch
Understanding: Detached HEAD means you're not on any branch - you're directly on a commit. Any commits you make won't belong to a branch unless you create one. It's useful for viewing old code or quick experiments.
Branch Management Strategies
Short-lived Branches:
- Feature branches deleted after merge
- Typically live for days or weeks
- Keep main branch clean and stable
Long-lived Branches:
- main/master - production code
- develop - integration branch
- staging - pre-production testing
- May live for months or years
Personal Branches:
- Prefix with your name: john/feature-x
- Experiment freely
- Delete or merge when done
Practical Branch Workflow
Complete workflow example:
# 1. Start from main
git switch main
git pull origin main
# 2. Create feature branch
git switch -c feature/user-profile
# 3. Work on feature (multiple commits)
git add profile.js
git commit -m "Add user profile component"
git add profile.css
git commit -m "Style user profile page"
# 4. Keep branch updated with main
git switch main
git pull origin main
git switch feature/user-profile
git merge main # Or rebase
# 5. Push feature branch
git push -u origin feature/user-profile
# 6. After PR merge, clean up
git switch main
git pull origin main
git branch -d feature/user-profile
git push origin --delete feature/user-profile
Viewing Branch Differences
Compare branches to understand differences:
# Show commits in feature not in main
git log main..feature-branch
# Show commits in main not in feature
git log feature-branch..main
# Show file differences between branches
git diff main..feature-branch
# Show only changed file names
git diff --name-only main..feature-branch
# Show stats of changes
git diff --stat main..feature-branch
# Compare specific file across branches
git diff main..feature-branch -- path/to/file.js
Practice Exercise:
Scenario: Create a complete branch workflow:
- Create a new feature branch called
feature/add-footer
- Make two commits on this branch
- List all branches and confirm you're on the feature branch
- Switch back to main
- View the differences between main and your feature branch
- Delete the feature branch
Commands:
# 1. Create and switch to feature branch
git switch -c feature/add-footer
# 2. Make changes and commit
echo "<footer>Copyright 2024</footer>" > footer.html
git add footer.html
git commit -m "Add footer HTML structure"
echo "footer { background: #333; }" > footer.css
git add footer.css
git commit -m "Add footer CSS styling"
# 3. List branches
git branch -v
# 4. Switch to main
git switch main
# 5. View differences
git log main..feature/add-footer --oneline
git diff main..feature/add-footer --stat
# 6. Delete branch (only if merged or use -D to force)
git branch -d feature/add-footer
Branch Best Practices
✓ DO:
- Create branches for every feature/bugfix
- Use descriptive branch names
- Keep branches short-lived
- Delete merged branches
- Regularly update feature branches with main
- Set upstream tracking for remote branches
- Review changes before switching branches
✗ DON'T:
- Work directly on main/master
- Let branches become stale (outdated)
- Use vague names like "test" or "branch1"
- Force switch with uncommitted changes
- Keep old merged branches around
- Share personal experiment branches
- Forget to pull main before creating branch
Summary
In this lesson, you learned:
- What branches are and why they're essential for development
- Creating branches with
git branch and git switch -c
- Switching between branches safely
- Listing branches with various filters
- Branch naming conventions and best practices
- Deleting and renaming branches
- Setting up tracking relationships with remote branches
- Understanding detached HEAD state
- Complete branch workflows for features and bugfixes
Next Up: In the next lesson, we'll explore merging branches - combining different lines of development and handling merge conflicts!