Skip to main content

Git Branching & Merging

Branching is Git’s killer feature. Create branches in milliseconds, experiment freely, and merge with confidence.

Why Branching Matters

Git Branching

Parallel Development

Multiple features in progress simultaneously without interference

Safe Experimentation

Try ideas without risking the main codebase

Code Review

Review changes before merging to main

Clean History

Organize work into logical units

Understanding Branches

A branch is just a pointer to a commit. That’s it!
# List all branches
git branch

# List with last commit
git branch -v

# List all branches (including remote)
git branch -a

Creating Branches

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

# Create and switch to it
git checkout -b feature/user-auth

# Modern syntax (Git 2.23+)
git switch -c feature/user-auth

Switching Branches

# Switch to existing branch
git checkout main
# or
git switch main

# Switch to previous branch
git checkout -
Before switching branches: Commit or stash your changes! Git won’t let you switch if you have uncommitted changes that would be overwritten.

Branch Naming Conventions

# Feature branches
git checkout -b feature/add-login
git checkout -b feature/payment-integration

# Bug fixes
git checkout -b fix/login-timeout
git checkout -b fix/memory-leak

# Hotfixes (urgent production fixes)
git checkout -b hotfix/security-patch

# Release branches
git checkout -b release/v1.2.0

# Experimental
git checkout -b experiment/new-architecture

Merging Branches

Fast-Forward Merge

When there are no new commits on the target branch:
# On main branch
git checkout main

# Merge feature branch
git merge feature/user-auth
Before:
main:    A---B
              \
feature:       C---D

After (fast-forward):
main:    A---B---C---D

Three-Way Merge

When both branches have new commits:
git checkout main
git merge feature/user-auth
Before:
main:    A---B---E
              \
feature:       C---D

After (merge commit):
main:    A---B---E---M
              \     /
feature:       C---D

Resolving Merge Conflicts

Conflicts happen when the same lines are changed in both branches.

Example Conflict

git merge feature/redesign
# Auto-merging index.html
# CONFLICT (content): Merge conflict in index.html
# Automatic merge failed; fix conflicts and then commit the result.

Conflict Markers

<<<<<<< HEAD
<h1>Welcome to My Site</h1>
=======
<h1>Welcome to Our Platform</h1>
>>>>>>> feature/redesign
  • <<<<<<< HEAD: Your current branch’s version
  • =======: Separator
  • >>>>>>> feature/redesign: Incoming branch’s version

Resolving

1

Open the conflicted file

# See which files have conflicts
git status
2

Edit the file

Remove conflict markers and choose the correct version:
<h1>Welcome to Our Platform</h1>
3

Stage the resolved file

git add index.html
4

Complete the merge

git commit  # Message pre-filled

Conflict Resolution Tools

# Use a visual merge tool
git mergetool

# Abort the merge
git merge --abort

# See conflicts
git diff --name-only --diff-filter=U

Deleting Branches

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

# Force delete (even if not merged)
git branch -D experiment/failed-idea

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

Branch Management

Viewing Branches

# Branches merged into current branch
git branch --merged

# Branches not yet merged
git branch --no-merged

# Branches with last commit info
git branch -vv

Renaming Branches

# Rename current branch
git branch -m new-name

# Rename another branch
git branch -m old-name new-name

Common Branching Workflows

Feature Branch Workflow

# 1. Create feature branch from main
git checkout main
git pull origin main
git checkout -b feature/add-comments

# 2. Work on feature
# ... make changes ...
git add .
git commit -m "feat: add comment system"

# 3. Keep feature branch updated
git checkout main
git pull origin main
git checkout feature/add-comments
git merge main  # Or rebase

# 4. Push and create pull request
git push origin feature/add-comments
# Create PR on GitHub/GitLab

# 5. After PR is merged, clean up
git checkout main
git pull origin main
git branch -d feature/add-comments

Gitflow Workflow

# Main branches: main (production), develop (integration)

# Start a feature
git checkout develop
git checkout -b feature/new-feature

# Finish feature
git checkout develop
git merge --no-ff feature/new-feature
git branch -d feature/new-feature

# Start a release
git checkout -b release/1.2.0 develop
# ... version bumps, bug fixes ...
git checkout main
git merge --no-ff release/1.2.0
git tag -a v1.2.0
git checkout develop
git merge --no-ff release/1.2.0
git branch -d release/1.2.0

# Hotfix
git checkout -b hotfix/1.2.1 main
# ... fix ...
git checkout main
git merge --no-ff hotfix/1.2.1
git tag -a v1.2.1
git checkout develop
git merge --no-ff hotfix/1.2.1
git branch -d hotfix/1.2.1

Trunk-Based Development

# Everyone works on main or very short-lived branches
git checkout main
git pull origin main
git checkout -b quick-fix
# ... make changes ...
git commit -am "fix: resolve login issue"
git push origin quick-fix
# Immediate merge after CI passes

Merge Strategies

Merge (Default)

git merge feature/new-ui
# Creates a merge commit
Pros: Preserves complete history
Cons: Can create a messy history with many merge commits

Squash Merge

git merge --squash feature/new-ui
git commit -m "feat: add new UI design"
# Combines all feature commits into one
Pros: Clean history
Cons: Loses individual commit history

Rebase (Advanced)

git checkout feature/new-ui
git rebase main
# Replays feature commits on top of main
Pros: Linear history
Cons: Rewrites history (don’t rebase public branches!)

Practical Examples

Example 1: Feature Development

# Start feature
git checkout -b feature/dark-mode

# Make commits
echo "dark theme CSS" > dark.css
git add dark.css
git commit -m "feat: add dark mode styles"

echo "toggle button" > toggle.js
git add toggle.js
git commit -m "feat: add dark mode toggle"

# Merge to main
git checkout main
git merge feature/dark-mode

# Clean up
git branch -d feature/dark-mode

Example 2: Handling Conflicts

# Create conflict scenario
git checkout -b branch-a
echo "Version A" > file.txt
git add file.txt
git commit -m "Add version A"

git checkout main
git checkout -b branch-b
echo "Version B" > file.txt
git add file.txt
git commit -m "Add version B"

# Try to merge
git checkout main
git merge branch-a  # Success
git merge branch-b  # CONFLICT!

# Resolve
# Edit file.txt, choose version
git add file.txt
git commit

# Clean up
git branch -d branch-a branch-b

Best Practices

  • Merge within days, not weeks
  • Reduces merge conflicts
  • Easier code review
git pull origin main
# Resolve any conflicts
git push origin feature/my-feature
# Local
git branch -d feature/completed

# Remote
git push origin --delete feature/completed
feature/user-authentication
fix/login-timeout
my-branch
test

Troubleshooting

”Cannot switch branches - uncommitted changes"

# Option 1: Commit changes
git add .
git commit -m "WIP: work in progress"

# Option 2: Stash changes
git stash
git checkout other-branch
git stash pop

"Merge conflict in binary file"

# Choose theirs
git checkout --theirs file.png
git add file.png

# Choose ours
git checkout --ours file.png
git add file.png

"Accidentally committed to wrong branch”

# Move commit to correct branch
git checkout correct-branch
git cherry-pick abc123  # SHA of the commit

# Remove from wrong branch
git checkout wrong-branch
git reset --hard HEAD~1

Key Takeaways

  • Branches are lightweight pointers
  • Create branches freely for features, fixes, experiments
  • Merge conflicts are normal—learn to resolve them
  • Delete branches after merging
  • Choose a workflow that fits your team

Next: Git Collaboration →