Chapter 99·Beginner·9 min read
Git Branches & Merging, Without Fear
A plain-English guide to Git branches and merging — what a branch really is, why branching is cheap, how a merge combines two lines of work, fast-forward vs merge commits, and the common ancestor idea that makes it all safe. The mental model that removes the fear.
July 14, 2026
Branching has a reputation for being the scary part of Git — the place where things go wrong and people paste commands they don't understand. It shouldn't. In the last chapter we established that a branch is just a label on a commit, and that single fact drains almost all the fear out of branching and merging. This chapter builds the mental model so that when you do run the commands, you know exactly what Git is doing and why.
A branch is a label, not a copy
Say it once more, because it's the whole game: a branch is a pointer to a commit. When you create a branch, Git doesn't copy your files, duplicate your project, or do anything expensive. It writes a new label pointing at the commit you're currently on. That's it.
When you make a new commit on feature, the feature label moves forward to the new commit, while main stays put. Now the two branches point at different commits, and history has diverged into two lines. Nothing was duplicated — you just have two labels that have drifted apart. This is why real teams create branches constantly, for even tiny changes: they're nearly free.
Why you branch in the first place
The point of a branch is isolation. Your team's stable, shippable code lives on main. You want to build a new feature that will take a few days and might break things along the way. If you edit main directly, every half-finished change is in everyone's way, and a broken commit blocks the whole team.
So instead you branch. You make a feature branch, do all your messy in-progress work there — commit, undo, commit again — while main stays clean and deployable. Meanwhile your teammates branch off main for their work. Everyone develops in parallel, each on their own line, and nobody steps on anyone else. When your feature is done and working, you bring it back into main by merging.
Merging: combining two lines
A merge takes the work from one branch and integrates it into another. The everyday case is: you've finished your feature branch and want its commits to become part of main. Git has two ways to do this, and knowing which is happening removes a lot of confusion.
Fast-forward: the trivial case
Suppose you branched off main, made some commits, and — crucially — main didn't move while you worked. Then merging is trivial: main is simply "behind" your feature branch on the same straight line. Git just slides the main label forward to catch up. This is a fast-forward merge, and it creates no new commit — the history stays perfectly linear.
The three-way merge: when both branches moved
The more interesting case is when both branches gained commits after they split — you added work on feature, and someone else added work on main. Now history has genuinely forked, and there's no straight line to slide along. Git has to actually combine two divergent sets of changes.
To do it, Git finds the common ancestor: the last commit both branches shared before they diverged. With three points in hand — the common ancestor and the two branch tips — Git can work out what each side changed relative to that shared starting point, and combine them. This is called a three-way merge, and it produces a new merge commit: a special commit with two parents, one from each branch, tying the two histories together.
Reading a merge in history
After a three-way merge, history has a visible fork-and-join shape: two lines splitting from a common ancestor and coming back together at the merge commit. That merge commit with two parents is the seam. Being able to picture that shape is what makes commands like log, and later rebase, make sense — you're always looking at a graph of snapshots joined by parent links, exactly the structure from the previous chapter.
The fear, removed
Put the pieces together and branching stops being intimidating. Creating a branch is writing a label — free and reversible. Working on it isolates your mess from everyone else's stable code. Merging is Git combining two lines from the point they last agreed, either by sliding a label forward or by making one merge commit with two parents. There's no hidden magic and nothing you can't inspect. The one place a merge genuinely needs a human is when two people changed the same lines — and handling that calmly is exactly what the merge-conflicts chapter is for. Before that, though, we need to look at a piece of Git that sits between your edits and your commits: the staging area.