Git/
Lesson

You've branched off, built an amazing feature, committed your work, and now you're ready to share it with the world. But there's a gap between your feature branch and the main codebase. How do you bridge it?

Merging is the moment of convergence. It's when the parallel universes of your branches come back together, combining different streams of work into a single, unified history. Done right, it's seamless. Done wrong... well, that's when conflicts happen (we'll cover those next).

The fundamental rule of merging

Before we look at the command, let's understand the mental model. Merging always happens into the branch you're currently on. Think of it as "pulling in" work from another branch.

# You're on main, pulling in feature-navbar
git checkout main
git merge feature-navbar

This says: "Take everything from feature-navbar and add it to main." The branch you specify (feature-navbar) stays exactly as it is. The branch you're on (main) gets updated.

This is the most common mistake beginners make, they try to merge from the wrong branch. Remember: checkout the destination, merge the source.

AI pitfall
AI assistants sometimes suggest merging without pulling first. They'll say "just run git merge feature-branch" without mentioning git pull origin main. If your teammate pushed changes to main while you were working, you're merging into an outdated version. Always pull before you merge: git checkout main && git pull origin main && git merge feature-branch.
02

Two ways to merge: fast-forward vs merge commitWhat is commit?A permanent snapshot of your staged changes saved in Git's history, identified by a unique hash and accompanied by a message describing what changed.

Git has two different strategies for merging, and which one it chooses depends on the state of your branches.

Fast-forward mergeWhat is fast-forward merge?A Git merge where the branch pointer simply moves forward because there is no divergent history, resulting in no merge commit.: the simple path

Imagine you created feature-login from main, made two commits on your feature branch, and main hasn't changed at all in the meantime:

Before merge:

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

There's a straight line from main to feature. Git can simply move the main pointer forward to catch up:

After fast-forward merge:

main:     A---B---C---Dfeature:  (same as main now)

No new commit is created. Git just slides the main pointer forward. This is clean, simple, and preserves linear history.

Run this:

git checkout main
git merge feature-login
# Output: Updating a1b2c3d..e4f5g6h
#         Fast-forward

The "Fast-forward" message tells you exactly what happened.

Merge commit: when histories diverge

Now imagine a more realistic scenario. While you were working on feature-login, your teammate pushed changes to main:

Before merge:

main:     A---B---E       ← your teammate added commit E
              \
feature:      C---D       ← you added commits C and D

The histories have diverged. Git can't simply move main forward because there's new work on main that isn't in your feature branch. Instead, Git creates a merge commit: a special commit that has two parents:

After merge commit:

main:     A---B---E---F
              \      /   ← commit F has two parents (E and D)
feature:      C---D

Commit F is the merge commit. It combines the changes from both branches.

Merge typeWhen it happensNew commit?History shape
Fast-forwardMain hasn't changedNoLinear
Merge commitBoth branches have new commitsYesDiamond/fork
--no-ff mergeForced by youYesAlways shows branch
Why two parents? Most commits have one parent, the commit that came before them. Merge commits are special because they have two (or more) parents, representing the fact that they combine work from multiple branches. When you look at your history later, you can see exactly where branches merged.
03

The complete merge workflow

In professional development, merging isn't just running git merge. It's a careful process designed to prevent disasters. Here's the full workflow:

Step 1: Verify your feature branch is ready

Before merging, make sure your feature branch is clean and complete:

git checkout feature-navbar
git status  # Should show "nothing to commit, working tree clean"

Step 2: Switch to main and update it

This is critical. You want to merge into the latest version of main, not an outdated one:

git checkout main
git pull origin main  # Get any changes from remote
Why pull first? If your teammate merged their feature while you were working, you want to merge on top of their changes, not create a confusing mess. Pulling ensures you're merging into the current state of the project.

Step 3: Merge your feature branch

Now you're ready:

git merge feature-navbar

Step 4: Verify and push

Check that the merge worked:

git log --oneline --graph
git push origin main

Step 5: Clean up

Your feature branch has served its purpose. Delete it:

git branch -d feature-navbar
git push origin --delete feature-navbar
04

When to force a merge commitWhat is commit?A permanent snapshot of your staged changes saved in Git's history, identified by a unique hash and accompanied by a message describing what changed.

Sometimes you want a merge commit even when Git could do a fast-forward. Why? Documentation. A merge commit clearly shows in your history where a feature branch started and ended.

git merge --no-ff feature-navbar

The --no-ff flag means "no fast-forward." Even if Git could fast-forward, it creates a merge commit instead.

Fast-forward (hard to see what was a feature):
main: A---B---C---D---E---F

No fast-forward (clear feature boundaries):
main: A---B---E-------F
          \         /
           C---D---

Many teams prefer --no-ff because it preserves the story of their development.

05

Checking what's been merged

Over time, you'll accumulate branches. Some are merged, some aren't. Git helps you figure out which is which:

# See branches that are already merged into your current branch
git branch --merged

# See branches that are NOT merged (don't delete these!)
git branch --no-merged
CommandShowsSafe to delete?
git branch --mergedBranches already mergedYes, work is preserved
git branch --no-mergedBranches with unmerged workNo, you'll lose work
06

Aborting a merge

Sometimes you start a merge and realize you're not ready. Git lets you abort:

git merge --abort

This returns you to the state before the merge started. Use this when the merge conflicts are more complex than expected, or you forgot to pull main first.

07

Quick reference

CommandWhat it doesWhen to use it
git merge branchMerge branch into currentIntegrate finished work
git merge --no-ff branchForce merge commitPreserve branch history
git merge --abortCancel in-progress mergeSomething went wrong
git branch --mergedList merged branchesFind safe deletions
git branch -d branchDelete merged branchPost-merge cleanup
javascript
# Switch to main branch
git checkout main

# Merge feature branch into main
git merge feature-login

# Create a merge commit even if fast-forward is possible
git merge --no-ff feature-navbar

# See merged branches
git branch --merged