Skip to main content

Branching & Merging

Branches let you work on features, fixes, or experiments in isolation without affecting the main codebase. They're lightweight in Git — just pointers to commits — so use them freely.

Creating and Switching Branches

# Create a new branch
git branch feature/user-auth

# Switch to it
git switch feature/user-auth

# Or create and switch in one step
git switch -c feature/user-auth

The older git checkout -b command does the same thing, but git switch is the modern, more intuitive alternative.

Listing Branches

# List local branches
git branch

# List all branches including remote
git branch -a

# See which branches are merged into current branch
git branch --merged

Merging

When your feature is ready, merge it into the target branch:

# Switch to the branch you want to merge INTO
git switch main

# Merge the feature branch
git merge feature/user-auth

Fast-Forward Merge

If main hasn't moved since you branched off, Git just moves the pointer forward. No extra commit is created:

# Before: main -> A -> B, feature -> A -> B -> C -> D
# After:  main -> A -> B -> C -> D
git merge feature/user-auth

Three-Way Merge

If both branches have new commits, Git creates a merge commit that ties them together:

git merge feature/user-auth
# Creates a new merge commit with two parents

To always create a merge commit (even when fast-forward is possible):

git merge --no-ff feature/user-auth

Rebasing

Rebase replays your commits on top of another branch, creating a linear history:

# On feature branch
git switch feature/user-auth

# Rebase onto main
git rebase main

Before rebase:

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

After rebase:

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

The commits D and E are recreated as D' and E' with new hashes.

Important: Never rebase commits that have been pushed and shared with others. Rebasing rewrites history, which causes problems for anyone who has based work on the original commits.

Deleting Branches

After merging, clean up:

# Delete a merged branch
git branch -d feature/user-auth

# Force-delete an unmerged branch
git branch -D experimental-feature

# Delete a remote branch
git push origin --delete feature/user-auth

Branching Strategies

GitHub Flow

Simple and effective for most teams:

  1. main is always deployable
  2. Create a feature branch from main
  3. Open a pull request when ready
  4. Merge into main after review
  5. Deploy from main

Git Flow

More structured, used for projects with scheduled releases:

  • main — production code
  • develop — integration branch
  • feature/* — new features branch from develop
  • release/* — release preparation
  • hotfix/* — urgent production fixes

Trunk-Based Development

The simplest approach — everyone commits to main (or short-lived branches) with frequent small merges. Relies on feature flags and strong CI.

Practical Tips

  • Keep branches short-lived. Long-running branches accumulate conflicts.
  • Use descriptive names: feature/add-search, fix/login-redirect, chore/update-deps.
  • Merge main into your feature branch regularly to stay up to date.
  • Delete branches after merging to keep the repository clean.