Merging Branches
After developing a feature on a branch, you'll want to integrate it back into your main branch. This is called merging.
What is Merging?
Merging combines the changes from one branch into another:
Before merge:
main: A ← B ← C
\
feature: D ← E
After merge:
main: A ← B ← C ← ← ← M
\ /
feature: D ← E
Types of Merges
Fast-Forward Merge
When the target branch has no new commits since the source branched off:
Before:
main: A ← B ← C
↑
main
feature: D ← E
↑
feature
After (fast-forward):
main: A ← B ← C ← D ← E
↑
main
feature
Git just moves the main pointer forward. No merge commit needed.
git switch main
git merge feature
# Fast-forward merge
Output:
Updating abc123..def456
Fast-forward
login.js | 25 ++++++++++++++++
1 file changed, 25 insertions(+)
Three-Way Merge
When both branches have new commits:
Before:
main: A ← B ← C ← F
\
feature: D ← E
After:
main: A ← B ← C ← F ← M
\ /
feature: D ← E
Git creates a merge commit (M) with two parents.
git switch main
git merge feature
# Three-way merge, creates merge commit
Performing a Merge
Basic Merge
# Switch to the target branch
git switch main
# Merge the source branch
git merge feature
# The feature branch still exists
git branch -d feature # Delete if done
Merge with Custom Message
git merge feature -m "Merge feature branch: add user login"
No Fast-Forward
Force a merge commit even when fast-forward is possible:
git merge --no-ff feature
This preserves the branch history:
With --no-ff:
main: A ← B ← C ← ← ← M
\ /
feature: D ← E
Without --no-ff (fast-forward):
main: A ← B ← C ← D ← E
↑
(feature history lost)
Squash Merge
Combine all commits into a single commit:
git merge --squash feature
git commit -m "Add login feature"
Before:
feature: D ← E ← F (3 commits)
After squash merge:
main: ... ← X (single commit with all changes)
The feature branch commits are combined. Original history is lost in main.
Merge Options
| Option | Description |
|---|---|
--no-ff | Always create merge commit |
--ff-only | Only merge if fast-forward possible |
--squash | Combine into single commit |
--no-commit | Merge but don't auto-commit |
--abort | Cancel merge in progress |
Understanding Merge Commits
A merge commit has two (or more) parents:
git log --oneline
# abc123 Merge branch 'feature' into main
# def456 Add login form (from feature)
# 789abc Update homepage (from main)
git show abc123
# Shows merge commit with both parents
Exercise: Merge Branches
Create a feature branch, make commits, and merge it back:
Merge Strategies
Git uses different strategies depending on the situation:
Recursive (Default)
Used for three-way merges. Handles most cases well.
git merge -s recursive feature
Ours
Keep our version of everything (discard their changes):
git merge -s ours feature
Octopus
Merge multiple branches at once:
git merge feature1 feature2 feature3
Viewing Merge History
# See merge commits
git log --merges
# See non-merge commits
git log --no-merges
# Graphical view
git log --oneline --graph
# First-parent only (main branch history)
git log --first-parent
Aborting a Merge
If something goes wrong during a merge:
git merge --abort
This restores your branch to the state before the merge started.
Best Practices
1. Update Before Merging
git switch main
git pull # Get latest changes
git switch feature
git merge main # Update feature with main's changes
# Resolve any conflicts
git switch main
git merge feature # Now merge feature to main
2. Use --no-ff for Feature Branches
git merge --no-ff feature -m "Merge feature: user authentication"
Preserves the fact that a feature was developed on a branch.
3. Delete Merged Branches
git branch -d feature
Keep your branch list clean.
4. Test Before Merging
Always verify the merge doesn't break anything:
git merge feature
npm test # Run tests
npm run build # Verify build
Summary
- Merging combines changes from one branch into another
- Fast-forward merges just move the pointer (no merge commit)
- Three-way merges create a merge commit with two parents
- Use
--no-ffto preserve branch history - Use
--squashto combine commits - Always merge from an updated main branch
- Use
git merge --abortto cancel a problematic merge
In the next lesson, we'll learn how to handle merge conflicts.

