git merge
intermediateFold the history of another branch into yours.
git mergeWhat it does
git merge takes the commits from another branch and joins them with your current branch. If they diverged, Git performs a three-way merge — comparing the two tips against their common ancestor — and writes a special merge commit with two parents. The other branch stays untouched.
The merge commit links both histories with a second parent edge
Watch it — press play
A narrated, step-by-step walkthrough that shows how to do it — not just theory. It adapts to the learner mode you picked in the top bar.
Step 1
Two branches, two timelines
Your feature branch and main have both moved since they split from the same commit.
git merge featureDiverged from commit 4b7c2a5 — the merge base
Under the hood
Fast-forward: not really a merge
If your branch hasn't moved, merging is just sliding your branch pointer forward to the other branch's tip. No new commit, no merge commit — a pure pointer move.
before: main ▸ a — b — c
feat ▸ a — b — c — d
after: main ▸ a — b — c — d (pointer only)Diverged: the three-way merge
When both branches have new commits, Git finds the merge base (the most recent common ancestor). It diffs base→yours and base→theirs, then combines both sets of changes.
base
/ \
yours theirs
\ /
merge commit (two parents)Blobs merge, not lines
For each file, Git reads the three blob versions, runs a word/line diff, and if both sides changed different regions, automatically stitches them together. Pure insertions on both sides never conflict.
A conflict is a file with both answers
When both sides edit the same lines, Git refuses to guess. It writes both versions into the file with <<<<<<< / ======= / >>>>>>> markers and marks the path as conflicting. The merge stops; you resolve and commit.
Resolve = edit, then add, then continue
Keep one side, both, or a blend — delete the marker lines — and git add the file to mark it resolved. Then git merge --continue (or a plain commit) closes the merge. Abort anytime before that with git merge --abort: the only thing you throw away is the half-baked attempt.
Command anatomy
--no-ffForce a merge commit even when fast-forward is possible.
--squashStitch the merged changes into one unstaged change — no merge commit.
--abortCancel a conflicted merge and restore the pre-merge state.
-mOverride the auto-generated merge message.
When to reach for it
Integrating a feature branch back into main after review.
You want to preserve the exact branches in history (history is honest).
Combined with --no-ff for a visible 'merge bubble' in release branches.
Practice
A real repo, pre-seeded with history, runs right here — stage, commit, branch, stash, diff, even hit and resolve a real merge conflict. Nothing to install, nothing leaves your machine.
Open practice playground