Merging branches

Git · Practical · 10 min

Merging is how finished work lands on main; knowing the two kinds keeps history readable.

git merge <branch> brings the commits of <branch> into the branch you are on. There are two outcomes.

Fast-forward: if your current branch hasn't moved since <branch> was created, its commits simply sit on top of yours. Git just slides your pointer forward; no new commit is made and history stays a straight line.

Three-way merge: if both branches have new commits, Git finds their merge base (the last common ancestor), compares each side with it, and combines the changes. It records the result as a merge commit with two parents. Changes to different files, or different parts of the same file, combine automatically; overlapping edits become conflicts (next lesson).

You can control which you get:

  • git merge --no-ff feature always creates a merge commit, even when a fast-forward is possible, preserving the fact that a group of commits was one feature.
  • git merge --ff-only feature refuses unless a fast-forward is possible. Good for updating a local main from origin/main without accidental merges.
  • git merge --squash feature stages the combined changes as one new commit you then create, without recording the branch as merged.

After merging, delete the feature branch with git branch -d; its commits are safe in main's history. git branch --merged lists branches already merged into the current one, handy for cleanup.

Merge never rewrites existing commits. That makes it safe on shared branches, at the price of merge commits in the graph.

Example

git switch main
git merge feature/login            # Fast-forward (main hadn't moved)

git switch main
git merge --no-ff feature/search -m "Merge search feature"
git log --oneline --graph -5
# *   b4e7d21 Merge search feature
# |\
# | * 91aa3c0 Add search index
# * | 3f9a2c1 Fix totals
# |/
git branch --merged                # safe-to-delete branches
git branch -d feature/search

Remember

  • Fast-forward just moves the pointer; three-way merge makes a two-parent commit
  • The merge base is the common ancestor Git diffs both sides against
  • --no-ff keeps feature grouping; --ff-only refuses real merges
  • Merging never rewrites existing commits

Watch out for

  • Using --squash and then deleting the branch with -d — Git doesn't consider it merged, so -d refuses; that's expected.

Check yourself

  1. main has not moved since feature branched off. What does git merge feature (on main) do by default?
  2. Which commit does Git use as the reference point in a three-way merge?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging

Merging branches · Git · Topolearn