Branches

Table of Contents

  1. Why Branches?
  2. What a Branch Really Is
  3. Create a Branch and Switch to It
  4. Work on the Branch
  5. Switching Changes Your Files
  6. Merging: The Fast-Forward
  7. Merging: The Merge Commit
  8. Cleaning Up and Naming Branches
  9. Try It Yourself

1. Why Branches?

So far every commit has gone in a single line, on main. That's fine for small changes, but imagine you start building a new page, get halfway, and then need to fix an urgent typo on the live site. Your half-finished page is mixed in with everything else.

A branch is a separate line of work. You create one, make your commits there, and main stays exactly as it was. When the work is finished and working, you merge it back into main. If the idea fails, you delete the branch and main never knew.

In real teams the rule is usually: main always works. Every new feature or fix happens on its own branch first.

2. What a Branch Really Is

Branches sound heavy, but they're one of the lightest things in Git.

Each commit stores a pointer to the commit before it (its parent), so commits form a chain:

3f2a1c9 ← c47a2e9 ← 8b1e4d0 ← 1c7e5a2
                                  ↑
                                main ← HEAD

A branch is just a label pointing at one commit. When you commit, the label moves forward to the new commit. And HEAD — "you are here" from chapter 4 — points at the branch you're currently on.

That's all. Creating a branch doesn't copy any files; it just writes a new label. It's instant, even in a huge project.

3. Create a Branch and Switch to It

List your branches:

git branch
* main

There's one, and the * shows you're on it. Now create a branch for a new About page and switch to it in one step:

git switch -c add-about
Switched to a new branch 'add-about'

(-c means "create". To switch to a branch that already exists, leave it out: git switch main.)

git branch
* add-about
  main

Both labels point at the same commit for now:

3f2a1c9 ← c47a2e9 ← 8b1e4d0 ← 1c7e5a2
                                  ↑
                          main, add-about ← HEAD

You may also see git checkout -b add-about in older tutorials. It does the same thing. git switch is the newer, clearer command.

4. Work on the Branch

Create about.html:

<!DOCTYPE html>
<html>
  <head>
    <title>About Dara</title>
  </head>
  <body>
    <h1>About me</h1>
    <p>I'm a student who likes building things.</p>
    <p><a href="index.html">Back home</a></p>
  </body>
</html>

And add a link to it in index.html, just above </body>:

    <p><a href="about.html">About me</a></p>

Commit as usual:

git add .
git commit -m "Add about page"

Only the branch you're on moves forward. main stays behind:

3f2a1c9 ← c47a2e9 ← 8b1e4d0 ← 1c7e5a2 ← b3d5f82
                                  ↑         ↑
                                main    add-about ← HEAD

5. Switching Changes Your Files

Now for the part that surprises people. Keep your file manager or VS Code's file list open where you can see it, and switch back:

git switch main

about.html disappears, and the link vanishes from index.html. Don't panic — nothing is lost. Git changed the files in your working directory to match the commit main points at, and the About page didn't exist there yet. Switch back:

git switch add-about

…and it's back. One folder, many versions, and Git swaps between them in an instant.

If you have uncommitted changes that would be overwritten, Git refuses to switch and tells you why. Commit them (or throw them away with git restore) first. Always check git status before switching.

6. Merging: The Fast-Forward

The About page is finished. To bring it into main, switch to the branch you want to merge into, then merge the other branch:

git switch main
git merge add-about
Updating 1c7e5a2..b3d5f82
Fast-forward
 about.html | 11 +++++++++++
 index.html |  1 +
 2 files changed, 12 insertions(+)
 create mode 100644 about.html

Fast-forward means main hadn't moved since the branch was created, so Git didn't need to combine anything. It just slid the main label forward to the same commit:

3f2a1c9 ← c47a2e9 ← 8b1e4d0 ← 1c7e5a2 ← b3d5f82
                                            ↑
                                      main, add-about

(HEAD is on main, because that's the branch you switched to.)

7. Merging: The Merge Commit

Fast-forwards are the easy case. In real life, main often moves on while you're working on a branch — a teammate merged something, or you fixed a typo. Let's create that situation.

Start a branch for a contact page:

git switch -c add-contact

Create contact.html:

<!DOCTYPE html>
<html>
  <head>
    <title>Contact Dara</title>
  </head>
  <body>
    <h1>Say hello</h1>
    <p>Email me at dara@example.com</p>
    <p><a href="index.html">Back home</a></p>
  </body>
</html>
git add contact.html
git commit -m "Add contact page"

Now go back to main and make a different change there — edit the sentence in about.html:

git switch main
    <p>I'm a student in Phnom Penh who likes building websites.</p>
git add about.html
git commit -m "Update about page text"

The two branches have now gone in different directions:

                ┌── 7e1a0c6  "Update about page text"   ← main
... ← b3d5f82 ──┤
                └── 2f9d7b4  "Add contact page"         ← add-contact

Merge as before:

git merge add-contact

This time Git can't just slide a label forward. It combines the two lines of work and records the result as a new merge commit — a commit with two parents. Your editor opens with the message Merge branch 'add-contact'. That's a fine message: save and close.

See the shape of your history with:

git log --oneline --graph
*   5a8c3e1 (HEAD -> main) Merge branch 'add-contact'
|\
| * 2f9d7b4 (add-contact) Add contact page
* | 7e1a0c6 Update about page text
|/
* b3d5f82 (add-about) Add about page
* 1c7e5a2 Revert "Add favorite food"
...

Read the lines on the left as tracks: the two branches split after b3d5f82 and join again at the merge commit. main now has both the contact page and the new about text.

Git could combine these automatically because the two branches changed different parts of the project. When two branches change the same lines, Git can't decide on its own — that's a merge conflict, and it's the next chapter.

8. Cleaning Up and Naming Branches

Once a branch is merged, its label isn't needed any more. Delete it:

git branch -d add-about
git branch -d add-contact

This only deletes the label — the commits are safely part of main. Git even refuses with -d if a branch has commits that aren't merged anywhere, so you can't lose work by accident. (-D, capital, forces it. Be sure before you use that.)

Good branch names describe the work, in lowercase with dashes:

  • add-contact-page
  • fix-broken-footer-link
  • update-profile-photo

Many teams add a prefix such as feature/add-contact-page or fix/footer-link. Follow whatever your team does.

9. Try It Yourself

  1. Make a branch and watch it move. Create add-about, commit the About page, and use git log --oneline on both branches to see which commit each label points at.
  2. Watch your files change. Switch between main and add-about with your file list open, and see about.html appear and disappear.
  3. Fast-forward merge add-about into main.
  4. Make a merge commit. Create add-contact, commit there, then commit a different change on main, and merge. Look at git log --oneline --graph.
  5. Try a throwaway experiment. Create a branch called crazy-idea, delete half of index.html, and commit. Then switch back to main (everything is fine there) and delete the experiment with git branch -D crazy-idea. That's how cheap it is to try an idea.

Next, let's make two branches change the same line — on purpose.

Buy Me a Coffee

Found this tutorial helpful? Consider buying me a coffee to support more free content!