Branches let you develop features in isolation without breaking the main codebase. Understanding branching and merging is essential for any team using Git.

Why Branch?

  main:     A --- B --- C ----------- G (merge)
                   \             /
feature:            D --- E --- F
  
  • main stays stable and deployable
  • Feature work happens on separate branches
  • Merge when the feature is complete and tested

Branch Commands

  # List branches (* = current)
git branch

# Create a branch
git branch feature/login

# Switch to a branch
git checkout feature/login

# Create and switch in one command
git checkout -b feature/login

# Modern equivalent (Git 2.23+)
git switch -c feature/login

# Delete a merged branch
git branch -d feature/login

# Force delete unmerged branch
git branch -D feature/login

# Rename current branch
git branch -m new-name
  

A Complete Feature Workflow

  # Start from updated main
git checkout main
git pull origin main

# Create feature branch
git checkout -b feature/user-profile

# Work and commit
git add src/profile.js
git commit -m "Add profile page component"

git add src/profile.test.js
git commit -m "Add profile page tests"

# Push branch to remote
git push -u origin feature/user-profile
  

Open a Pull Request on GitHub/GitLab for code review.

Merging

  # Merge feature into main
git checkout main
git pull origin main
git merge feature/user-profile
git push origin main
  

Git creates a merge commit when histories diverged:

  Merge branch 'feature/user-profile'
  

Fast-Forward Merge

When main has no new commits since the branch was created, Git simply moves the pointer forward — no merge commit needed.

  git merge feature/quick-fix
# Fast-forward
  

Merge Conflicts

Conflicts occur when the same lines were changed in both branches:

  <<<<<<< HEAD
const greeting = "Hello";
=======
const greeting = "Hi there";
>>>>>>> feature/login
  

Resolve manually:

  1. Edit the file to keep the correct code
  2. Remove conflict markers (<<<<, ====, >>>>)
  3. Stage and commit:
  git add src/app.js
git commit -m "Resolve merge conflict in app.js"
  

Tools to help:

  git mergetool          # launch configured merge tool
git diff --name-only --diff-filter=U  # list conflicted files
  

Rebase

Rebase replays your commits on top of another branch — cleaner linear history:

  git checkout feature/login
git rebase main
  

Before:

  main:    A --- B --- C
              \
feature:       D --- E
  

After rebase:

  main:    A --- B --- C
                      \
feature:               D' --- E'
  

Golden rule: Never rebase commits that have been pushed and shared with others (unless the team agrees).

Interactive rebase to clean up commits:

  git rebase -i HEAD~3
# pick, squash, reword commits in editor
  

Branching Strategies

GitHub Flow (Simple)

  • main is always deployable
  • Feature branches merge via Pull Request
  • Deploy from main after merge

Best for: web apps, continuous deployment teams.

Git Flow (Structured)

  • main — production releases
  • develop — integration branch
  • feature/* — new features
  • release/* — release preparation
  • hotfix/* — emergency production fixes

Best for: scheduled releases, mobile apps.

Trunk-Based Development

  • Short-lived branches (< 1 day)
  • Frequent merges to main
  • Feature flags hide incomplete work

Best for: high-velocity teams with strong CI/CD.

Remote Branches

  # List remote branches
git branch -r

# Fetch without merging
git fetch origin

# Pull = fetch + merge
git pull origin main

# Pull with rebase
git pull --rebase origin main

# Delete remote branch
git push origin --delete feature/login
  

Stashing Before Switching

Uncommitted work when you need to switch branches:

  git stash push -m "WIP login form"
git checkout main
# ... do other work ...
git checkout feature/login
git stash pop
  

What Comes Next

Learn Advanced Git for cherry-pick, hooks, and bisect, then Collaboration for Pull Requests and code review workflows.