Ad – 728×90
🌿 Branching & Merging

Git Branches – What Are Branches and Why Use Them?

Branches are one of Git's most powerful features — and one of its most misunderstood. Under the hood, a branch is nothing more than a 41-byte text file containing a commit hash. Yet this tiny file enables you to work on multiple features simultaneously, experiment without risk, and collaborate with an entire team without stepping on each other's code.

⏱️ 15 min read 🎯 Beginner 📅 Updated 2026

What Is a Git Branch?

A Git branch is a lightweight, movable pointer to a specific commit. That's it. When you look inside .git/refs/heads/, you'll find one small text file per branch, each containing a single SHA-1 hash (40 characters + newline = 41 bytes).

Shell
# A branch is literally just a file containing a commit hash
cat .git/refs/heads/main
# a3f8c2d7e91b4a567890abcdef1234567890abcd

# List all branch files
ls .git/refs/heads/
# main  feature/login  bugfix/404

Because a branch is just a file with a hash, creating a new branch is instantaneous regardless of your project size. Git doesn't copy files or duplicate history — it simply writes a new 41-byte file.

ℹ️
Branches vs. other VCS

In older version control systems like SVN, creating a branch meant copying the entire project directory — an operation that could take minutes. In Git, creating a branch takes milliseconds. This is why Git developers use branches constantly for even small tasks.

Why Use Branches?

Branches solve a fundamental problem in software development: how do you work on new things without breaking what already works?

Use CaseWithout BranchesWith Branches
New feature development Risk breaking main codebase for entire team Develop in isolation, merge when ready
Bug fixes Partially written fixes mix with new feature code Clean, focused fix on its own branch
Experimentation Have to undo changes manually if experiment fails Just delete the branch — nothing is lost
Parallel work Team members block each other Each developer works on their own branch
Code review Hard to isolate what changed PR contains only branch changes vs main

The main (or master) Branch

When you run git init or git clone, Git automatically creates a default branch. This branch is conventionally named main (modern default) or master (older default). Git does not treat this branch specially — it has no built-in significance beyond being the starting point. The convention is that main contains stable, production-ready code.

Shell
# Check which branch name git init will use by default
git config --global init.defaultBranch
# main

# If you're on an older Git version (pre-2.28) you can set it:
git config --global init.defaultBranch main
ℹ️
main vs master

GitHub changed its default from master to main in October 2020. Git itself changed its default in version 2.28 (July 2020). If you see master in older tutorials or repositories, it is the same concept — just a naming convention. You can rename either branch at any time.

A Branch Is a Moving Pointer

Here's the key insight: when you make a new commit while on a branch, the branch pointer automatically moves forward to point at the new commit. You don't do anything — Git updates the branch file for you.

text
Before commit:
  main → C2 → C1

After "git commit":
  main → C3 → C2 → C1

The branch pointer moved from C2 to C3 automatically.

HEAD is a special pointer that tells Git which branch you're currently on. When you commit, Git moves the branch that HEAD points to forward.

Shell
# HEAD is also just a file
cat .git/HEAD
# ref: refs/heads/main
# This means: "I'm on the main branch"

# When HEAD points directly to a commit (detached HEAD state):
# HEAD → a3f8c2d7e91b...  (no branch name — just a hash)
⚠️
Detached HEAD state

If you check out a specific commit hash (not a branch name), HEAD points directly to that commit instead of a branch. You're in "detached HEAD" state. Any commits you make won't belong to any branch and can be lost. To save your work, create a branch: git switch -c new-branch-name.

Visualizing Branches

Let's trace through a real branching scenario with ASCII diagrams to make this concrete.

Starting point: commits on main

text
C1 ← C2 ← C3
              ↑
             main
              ↑
             HEAD

Create a feature branch and make commits

text
After: git switch -c feature/login
       (make 2 commits on feature/login)

C1 ← C2 ← C3
              ↑
             main

              ↖ C4 ← C5
                       ↑
               feature/login
                       ↑
                      HEAD

main still points at C3.
feature/login moved forward to C5.
HEAD follows feature/login.

Merge feature/login back into main

text
After: git switch main && git merge feature/login
       (fast-forward — see Merging lesson)

C1 ← C2 ← C3 ← C4 ← C5
                       ↑
                      main  (moved forward)
                       ↑
              feature/login
                       ↑
                      HEAD
Ad – 336×280

Checking branch state from the command line

Shell
# See a text graph of branches and commits
git log --oneline --graph --all

# Example output:
# * a1b2c3d (HEAD -> main, feature/login) Add login validation
# * 9f8e7d6 Add login form
# * 5c4b3a2 Initial project setup

📋 Summary

  • A branch is a lightweight movable pointer to a commit — stored as a 41-byte file in .git/refs/heads/.
  • Creating a branch is instantaneous — Git doesn't copy files or history.
  • Branches let you work in isolation: new features, bug fixes, and experiments stay separate from stable code.
  • main (or master) is the default branch by convention — Git doesn't treat it specially.
  • When you commit, the current branch pointer moves forward automatically.
  • HEAD points to the current branch (or directly to a commit in "detached HEAD" state).

FAQ

Can you have an unlimited number of branches? +

Yes, practically unlimited. Each branch is just a 41-byte file on disk, so you could have thousands of branches with almost no storage overhead. In practice, teams typically keep a modest number of active branches at any time and delete feature branches after merging. Long-lived stale branches become confusing and are considered bad practice.

What happens to a branch after you merge it? +

The branch pointer still exists after merging — Git does not delete it automatically. The commits from the merged branch are now reachable from the target branch, but the merged branch label remains until you explicitly delete it with git branch -d branch-name. It's good practice to delete feature branches after merging to keep the branch list clean.

Is the main branch special in any way? +

Not to Git itself — main is just a branch name like any other. What makes it special is convention and tooling. GitHub, GitLab, and most CI/CD tools use the default branch as the deployment target. Your team's workflow decides which branch is "protected" and requires pull requests. You could name your primary branch anything, though deviating from main creates unnecessary friction with tooling.

What is a detached HEAD and should I be worried? +

Detached HEAD means HEAD is pointing directly to a commit hash instead of a branch name. It happens when you run git checkout <commit-hash> or check out a tag. You can look around safely in this state, but any new commits you make won't be tracked by any branch. If you want to keep those commits, run git switch -c my-new-branch while still in detached HEAD state. Git will warn you clearly when you're in this state.