Branching and Merging

Reviewed & published by Brayan K

By the end of this lesson you'll be able to spin up an isolated branch to build a feature, switch between lines of work, merge them back, and clean up — the core skill that turns Git from "save button" into real team collaboration.

Part of the free Git course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.

What You'll Learn

1️⃣ Why Branches Exist

A branch is just a movable label that points at a commit. That's it — Git copies no files when you branch, it simply writes one new pointer, so creating a branch is instant even in a huge project. The point of a branch is isolation: you can build a half-finished feature, break things, and experiment freely without ever putting the shared main branch at risk. When the work is good you merge it back; if it's a dead end you throw the branch away and lose nothing else.

Your turn. Start a new feature on its own branch, prove you're on it, and make a commit. Fill in the three blanks marked ___ using the hints in the comments.

2️⃣ HEAD — "You Are Here"

HEAD is Git's "you are here" marker. Nearly always it points at the branch you're currently on, and that branch points at your latest commit — so HEAD → main → a1b2c3d. When you switch branches, HEAD simply moves to point at the other branch. It's a label tracking your position, not a separate copy of your code.

# HEAD is Git's "you are here" pointer. It normally points at the
# branch you're on, and that branch points at your latest commit:
#
#   HEAD -> main -> a1b2c3d (the commit you'd build the next one on top of)
#
# When you switch branches, HEAD just moves to point at the other branch.

# See where HEAD is pointing right now
git branch --show-current        # prints the current branch name, e.g. main

# Switching moves HEAD from one branch to another
git switch feature-login         # HEAD -> feature-login
git switch main                  # HEAD -> main again

# These are the SAME commit — HEAD is a label, not a separate copy:
git log -1 HEAD --oneline        # newest commit on the current branch

3️⃣ Merging Branches

Merging brings the commits from one branch into another. First switch to the branch you want to receive the work, then run git merge with the branch you want to pull in. Git picks one of two strategies automatically. A fast-forward happens when main hasn't moved since the branch split off — Git just slides the main label forward and history stays perfectly linear. A three-way merge happens when both branches gained commits — Git can't slide the label, so it builds a new merge commit with two parents to tie the lines of history together.

4️⃣ Deleting Merged Branches

Once a branch is merged, its commits live safely on the branch you merged into, so the branch label has done its job. Delete it with git branch -d name — the lower-case -d is the safe delete: Git refuses if the branch isn't fully merged, protecting you from losing commits. The capital -D is the force delete — it throws the branch away even if its work was never merged, so reach for it only when you genuinely want to discard that experiment.

Now put the whole loop together: switch to main, merge your finished feature, and safely delete it. Fill in the three blanks.

# 🎯 YOUR TURN — you finished "add-search" and want it on main.
# Replace each ___ then run it in your terminal.

# 1) Move to the branch that should RECEIVE the work
git switch ___                 # 👉 the main branch's name

# 2) Merge your finished feature branch in
git merge ___                  # 👉 the branch you built: add-search

# 3) The merge worked, so safely delete the merged branch
git branch ___ add-search      # 👉 the lower-case "safe delete" flag

# ✅ Expected output (a fast-forward, then the delete confirmation):
#    Updating a1b2c3d..7f3a1c2
#    Fast-forward
#     search.txt | 1 +
#     1 file changed, 1 insertion(+)
#    Deleted branch add-search (was 7f3a1c2).

5️⃣ Visualising Your History

Reading branches as plain text gets confusing fast. One command draws your entire repository as an ASCII graph — every branch, every merge, every commit — right in the terminal. Learn this early; it's the fastest way to build a mental picture of what your branches are doing.

# Reading branches as text is hard. This one command draws the whole
# repository as an ASCII graph — every branch, every merge, every commit.

git log --graph --oneline --all

#   --graph    draw the branch/merge lines on the left
#   --oneline  one short line per commit (hash + message)
#   --all      include ALL branches, not just the current one
#
# Tip: add --decorate to label which branch each commit belongs to
# (most modern Git versions show those labels automatically).

6️⃣ Rebase vs Merge

git rebase replays your commits on top of another branch for a clean, linear history instead of a merge commit. It's powerful but dangerous on shared branches. Follow the golden rule: never rebase commits you've already pushed, because rebasing rewrites history and breaks anyone who already pulled it.

# git rebase replays your commits on top of another branch,
# producing a clean, linear history instead of a merge commit.

# On your feature branch, replay its commits onto the latest main
git switch feature
git rebase main

# Then fast-forward main onto the rebased commits
git switch main
git merge feature

# GOLDEN RULE: never rebase commits you have already pushed and
# shared — rebasing rewrites history and breaks everyone else's work.
# Safe:      rebase YOUR local, unpushed feature branch onto main.
# Dangerous: rebase main or any branch others have pulled.

7️⃣ git stash — Quick Save

git stash temporarily shelves your uncommitted changes so you can switch branches with a clean working directory. When you come back, git stash pop restores everything exactly as it was — perfect for when an urgent bug interrupts your half-finished feature.

# Scenario: you're mid-change on feature-login but must fix a bug on main.

# 1. Shelve your uncommitted changes and clean the working directory
git stash

# 2. Switch to main and fix the bug
git switch main
git commit -am "Fix critical bug"

# 3. Go back to your feature and restore the shelved work
git switch feature-login
git stash pop

# Other stash commands
git stash list            # show all stashes (a last-in, first-out stack)
git stash apply           # restore the latest stash but KEEP it in the list
git stash drop            # delete the latest stash
git stash clear           # delete ALL stashes

Common Errors (and the fix)

Pro Tips

📋 Quick Reference

CommandPurpose
git branchList branches (current marked *)
git branch nameCreate a branch
git switch -c nameCreate and switch (≡ checkout -b)
git switch nameSwitch to an existing branch
git merge branchMerge branch into the current one
git branch -d nameSafe-delete a merged branch
git branch -D nameForce-delete an unmerged branch
git log --graph --oneline --allDraw the whole history as a graph
git stash / popShelve / restore uncommitted work

Mini-Challenge: Ship a Feature Branch

No commands given this time — just the plan and a blank canvas. Work through the whole branch lifecycle in your own terminal, then check your graph against the expected result in the comments.

# 🎯 MINI-CHALLENGE: ship a feature on its own branch
# No commands given — just the plan. Run each step in your terminal.
#
# 1. From main, create AND switch to a branch called "about-page"
# 2. Create a file (e.g. about.html), then add it and commit it
# 3. Draw the graph and confirm about-page is ahead of main
# 4. Switch back to main and merge about-page in
# 5. Delete the merged branch with the SAFE (lower-case) delete flag
#
# ✅ Expected: after the merge, "git log --graph --oneline --all" shows
#    about-page's commit sitting on the same line as main (a fast-forward),
#    and "git branch" no longer lists about-page.

# your commands here

🎉 Lesson Complete!

Practice quiz

What is a Git branch?

  • A full copy of every file in the project
  • A movable label that points at a commit
  • A remote server
  • A saved snapshot of your files

Answer: A movable label that points at a commit. A branch is just a lightweight, movable pointer to a commit; creating one copies no files.

Which command creates AND switches to a new branch in one step?

  • git branch -c name
  • git checkout name
  • git switch name
  • git switch -c name

Answer: git switch -c name. git switch -c name (equivalent to git checkout -b name) creates the branch and moves you onto it.

What is HEAD in Git?

  • The 'you are here' pointer to your current branch and commit
  • The first commit in the repo
  • The remote's main branch
  • The staging area

Answer: The 'you are here' pointer to your current branch and commit. HEAD points at the branch you're on, which points at your latest commit; it moves as you switch branches.

When does Git do a fast-forward merge?

  • Whenever you merge any branch
  • Only when there is a conflict
  • When the receiving branch had no new commits since the other split off
  • When both branches changed the same line

Answer: When the receiving branch had no new commits since the other split off. If main hasn't moved since the branch split off, Git just slides the label forward with no merge commit.

Before running git merge feature, which branch should you be on?

  • The feature branch
  • The branch you want to RECEIVE the work (e.g. main)
  • Any branch, it doesn't matter
  • A brand-new empty branch

Answer: The branch you want to RECEIVE the work (e.g. main). git merge pulls the named branch INTO the one you're on, so switch to the receiving branch first.

What does the lower-case git branch -d do?

  • Safely deletes a branch, refusing if it isn't fully merged
  • Force-deletes any branch
  • Creates a new branch
  • Renames a branch

Answer: Safely deletes a branch, refusing if it isn't fully merged. -d is the safe delete; Git refuses to remove a branch that has unmerged commits, protecting your work.

When does git merge create a new merge commit with two parents?

  • Always, on every merge
  • Never
  • When both branches gained commits since they diverged
  • Only on the first commit

Answer: When both branches gained commits since they diverged. A three-way merge commit is made when both branches advanced, so Git can't simply fast-forward.

What is the golden rule of git rebase?

  • Always rebase main
  • Rebase shared branches often
  • Rebase only after pushing
  • Never rebase commits you've already pushed and shared

Answer: Never rebase commits you've already pushed and shared. Rebasing rewrites history, so rebasing shared commits breaks everyone else's copy; only rebase your local work.

What does git stash do?

  • Shelves uncommitted changes and cleans the working directory
  • Permanently deletes your changes
  • Pushes changes to the remote
  • Creates a new branch

Answer: Shelves uncommitted changes and cleans the working directory. git stash tucks away uncommitted changes so you can switch branches with a clean working tree.

Which command draws your whole history, all branches, as an ASCII graph?

  • git status --branches
  • git branch --all
  • git log --graph --oneline --all
  • git show --graph

Answer: git log --graph --oneline --all. git log --graph --oneline --all draws every branch and merge as a compact graph.

Continue this course

Frequently asked questions

What's the difference between a branch and a commit?

A commit is a permanent saved snapshot of your files with its own ID (hash). A branch is just a lightweight, movable label that points at one commit — usually the latest one on that line of work. Making a new commit moves the branch label forward; making a new branch does not create any snapshots, it only adds another pointer.

Should I use git switch or git checkout?

Prefer git switch for changing branches and git switch -c to create-and-switch — it was added precisely to make branch work clearer and safer. git checkout still works and you'll see it in older tutorials, but it also does unrelated jobs (like restoring files), which is why Git split those duties out into switch and restore.

When does Git fast-forward instead of making a merge commit?

Git fast-forwards when the branch you're merging into has had no new commits since the other branch split off. There's nothing to reconcile, so Git just slides the label forward and history stays linear. If both branches gained commits, Git can't slide the label and instead creates a merge commit with two parents (a three-way merge).

What is HEAD?

HEAD is Git's 'you are here' pointer. Almost always it points at the branch you're currently on, which in turn points at your latest commit. When you switch branches, HEAD moves to the new branch — it's a label that tracks your position, not a separate copy of your code.

Is it safe to delete a branch after merging?

Yes. Once a branch is merged, its commits live on the branch you merged into, so deleting the original label loses nothing. Use git branch -d (lower-case) — it refuses to delete a branch that isn't fully merged, protecting you from accidental data loss. Reserve the capital -D for deliberately discarding unmerged work.