Advertisement
🌿 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
Advertisement

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

Branches: Parallel Lines of Work, Almost Free

A branch lets you develop a feature or fix in isolation without disturbing the stable main line. The reason branching is instant in Git: a branch is just a movable pointer to a commit — creating one writes a single tiny file, it doesn't copy your project.

git switch -c feature/login    # create + switch
# ...commit work on the feature...
git switch main
git merge feature/login        # bring it back into main
git branch -d feature/login    # delete the merged pointer

As you commit on a branch, its pointer advances while other branches stay put. All branches share the same commit history underneath — a branch just marks one tip of it. HEAD points to the branch you're currently on.

CommandDoes
git branchlist branches (* = current)
git switch namemove to a branch
git merge namecombine a branch into current

Why branch at all: it isolates in-progress work so main always stays deployable, lets several people work in parallel without stepping on each other, and makes code review possible (one branch = one pull request). The one rule: keep branches short-lived — merge within days, not weeks. Long-lived branches drift far from main and turn merging into a conflict nightmare. Name them descriptively (fix/login-crash, feature/checkout).

🏋️ Practical Exercise

  1. List branches with git branch.
  2. Note the default branch name (main).
  3. Understand that a branch is a movable pointer.
  4. See the current branch in git status.
  5. Visualize branches in a git log --graph.

🔥 Challenge Exercise

Explain what a Git branch actually is (a movable pointer to a commit) and why branching is cheap in Git. List your branches, identify the current one, and describe how HEAD relates to the active branch.

📋 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).

Interview Questions

  • What is a branch in Git?
  • Why are Git branches lightweight?
  • What is the default branch name?
  • How does HEAD relate to a branch?
  • How do you list all branches?

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.