Branch Basics: Create, Switch, Merge

Master branch basics: create, switch, merge in Git. Step-by-step tutorial with hands-on exercises, troubleshooting, and next steps for distributed collaboration.

Focus: branch basics: create, switch, merge

Sponsored

You’ve been committing happily on main, and everything feels fine. Then the day comes: you need to experiment with a wild refactor, fix a hot bug, or build a new feature that will take days — and you can’t afford to break everything you’ve already done. The pain is real: every commit you make on main is shared, and one wrong move can ripple through the whole team. That’s the moment you stop treating Git as a simple snapshot machine and start using its superpower: branches. In this lesson, you’ll learn the branch basics you need every day — creating, switching, and merging — so you can work fearlessly, keep your history clean, and make collaboration painless.

The problem this lesson solves

Without branches, every developer on a project commits to the same shared timeline. That means:

  • No isolation — Your half-finished feature sits right next to the release-ready code.
  • No parallel work — Two people touching different parts of the same file create constant merge chaos.
  • Fear of experimentation — One bad idea can poison the entire project history.

Branches solve this by letting you create independent lines of development. A branch is just a lightweight movable pointer to a specific commit. Creating a branch costs almost nothing — it’s not a copy of your files, it’s a label. You can create dozens of branches and switch between them at will, committing freely in each one, and merge them back together only when you’re ready.

Why this matters now: You’ve already mastered committing and viewing history. Branches are the natural next step — they let you shape that history without fear. Every serious Git workflow, from GitHub Flow to GitFlow, is built on branch basics.

Core concept / mental model

Think of Git’s commit history as a tree. The trunk is your main line (often main or master). A branch is a twig that grows from a particular commit. You can grow the twig as long as you like, add leaves (commits), and then either graft it back onto the trunk or let it die.

Here’s the key mental model:

  • Commit — A snapshot of your files with a unique ID.
  • Branch — A named pointer to a commit. When you make a new commit, the branch moves forward.
  • HEAD — A pointer that marks which branch you’re currently on. When you switch branches, Git updates HEAD and changes the files in your working directory to match that branch’s latest commit.

Branch creation is instant: git branch <name> just creates a new pointer at your current commit. Switching is also fast: git switch <name> updates HEAD and your working directory. Merging is the act of combining the history of one branch into another — Git takes the two lines of commits and creates a new commit that joins them.

Think of branches like bookmarks in a book — they don’t duplicate the story, they just mark different places. You can jump to any bookmark, read a few pages, then jump back.

How it works step by step

Step 1: Create a branch

To create a branch named feature/login, run:

git branch feature/login

This creates a pointer at your current commit. You’re still on main — the new branch exists, but you haven’t switched to it. Verify with git branch (lists branches, asterisk marks current).

Step 2: Switch to the branch

Newer Git encourages the switch command (Git 2.23+):

git switch feature/login

Now HEAD points to feature/login, and your working directory files are updated to match that branch’s latest commit. Important: if you have uncommitted changes, Git may refuse to switch if they conflict — see Troubleshooting below.

Shortcut: Create and switch in one command:

git switch -c feature/login

Step 3: Commit on the branch

Make your changes, stage, and commit normally. Your commits go only to feature/login. main stays untouched.

Step 4: Merge the branch back

When your feature is done, switch back to the target branch (usually main) and merge:

git switch main
git merge feature/login

Git will try to automatically combine changes. If both branches changed the same lines, you’ll hit a merge conflict — see Troubleshooting.

Pro tip: Always merge into the branch that should receive the changes. Never merge main into a feature unless you specifically want to sync it.

Hands-on walkthrough

Let’s build a real example step by step. Create a fresh repo and follow along.

1. Set up a workspace

mkdir git-branch-demo && cd git-branch-demo
git init
echo "Hello, world" > app.py
git add app.py
git commit -m "Initial commit"
Author: you@example.com
Date: ...

    Initial commit
git branch
# * main

2. Create and switch to a feature branch

git switch -c feature/greeting
# Switched to a new branch 'feature/greeting'

Edit app.py to change the greeting:

echo "Hello from the feature branch" > app.py
git add app.py && git commit -m "Update greeting"

3. Switch back to main and see the difference

git switch main
cat app.py
# Hello, world

Your change is safe on feature/greeting, and main stays clean.

4. Merge the feature branch

git merge feature/greeting
# Updating 5f9d...a3c2
# Fast-forward
#  app.py | 2 +-
#  1 file changed

Now main has the updated greeting.

Note: Because main hadn’t moved, Git could do a fast-forward merge — it just moved main forward to the tip of the feature branch. If main had new commits, you’d get a merge commit instead.

5. Verify the merged history

git log --oneline --graph
# * a3c2 (HEAD -> main) Update greeting
# * 5f9d Initial commit

Compare options / when to choose what

Approach When to use Pros Cons
git branch + git switch Classic, explicit flow Works everywhere, clear steps Two commands per branch switch
git switch -c Fast, everyday creation One command, fewer mistakes Requires Git 2.23+
git checkout -b Legacy scripts/older Git Backward compatible Mixing checkout concerns (files + branches) can confuse
git merge with fast-forward Linear, simple feature branches Cleanest history Not possible if parent branch has diverged
git merge --no-ff Team workflows that want merge commits Preserves feature history More commits, slightly larger log

Choosing the right merge mode: If you prefer a linear history (every commit on a single line), fast-forward merges are ideal — but they only work when the target branch hasn’t moved since the branch point. If you want to preserve the fact that a feature branch existed, use --no-ff to force a merge commit even when fast-forward is possible.

When to create branches: Create a new branch for any feature, bugfix, or experiment that will take more than one commit. For trivial one-line fixes, staying on main is often fine — but for anything that could destabilize, branch first.

Pro tip: Name your branches with a convention (e.g., feature/, bugfix/, hotfix/). It makes the history readable and helps CI/CD tools target the right branches.

Troubleshooting & edge cases

Error: “Your local changes would be overwritten by checkout”

You tried to switch branches but have uncommitted changes that conflict with the target branch. Git refuses to overwrite them. Fix by committing, stashing, or discarding (if safe):

# Commit the changes first
git add . && git commit -m "WIP"
# Or stash them
git stash
git switch feature
# ... later, restore stash
git stash pop

Merge conflict: “CONFLICT (content): Merge conflict in app.py”

Both branches changed the same area of a file. Git marks the file with conflict markers:

<<<<<<< HEAD
Hello from main
=======
Hello from feature
>>>>>>> feature/greeting

Edit the file to keep what you want, remove the markers, then complete the merge:

git add app.py
git commit -m "Resolve merge conflict"

Detached HEAD

If you accidentally check out a commit hash directly (e.g., git checkout a3c2f1), Git puts you in detached HEAD — you’re not on any branch. Any new commits are “floating”. To fix, create a branch or switch back to a named branch.

Accidentally merged the wrong branch

If you merged before you were ready and haven’t pushed, you can undo the merge with git reset --hard <commit-before-merge> (use --hard with caution — it discards uncommitted changes).

What you learned & what's next

You now have the core branch skills: creating branches with git branch or git switch -c, switching between them with git switch, and merging them back with git merge. You understand the mental model of branches as pointers, how HEAD tracks your current branch, and you can handle the two most common errors: overwrite warnings and merge conflicts. You can confidently isolate work, experiment without risk, and integrate changes when they’re ready.

What’s next: In the next lesson, you’ll expand from local branches to remote branches — pushing branches to a shared repository, tracking remote refs like origin/main, and pulling others’ work with git pull. That’s where branch basics meet real-world collaboration. You’ll also explore advanced merge strategies like rebasing to keep history clean. Practice these basics with your own repos, and you’ll be ready for distributed teamwork.

Practice recap

In your own sandbox repo, create two feature branches from the same starting commit. Make one change on each, then switch back and forth to see how your working directory changes. Merge one branch back into main, and then force a conflict by editing the same line on both branches. Resolve the conflict, then push your branch to a GitHub remote and open a pull request.

Common mistakes

  • Forgetting to switch to the target branch before merging — you merge into the branch you're currently on, not the branch you're thinking about.
  • Using git branch without switching, then wondering why your commits aren't on the new branch.
  • Trying to switch branches with uncommitted changes that conflict — Git will refuse, and beginners often panic or lose work instead of using git stash.
  • Leaving a branch unmerged and switching away, then losing track of it — either merge it or note it in git branch -v.

Variations

  1. Use the older git checkout -b to create and switch in one command if you're on Git before 2.23 or in a script that checks out many repos.
  2. Use git switch --detach to deliberately go into a detached HEAD state to inspect old commits — but avoid committing there.
  3. Use git merge --no-ff in team workflows to force a merge commit and preserve the feature branch's shape in history.

Real-world use cases

  • A developer creates a feature/refactor-auth branch to rewrite authentication, leaving main stable and safe for colleagues.
  • A hotfix branch hotfix/security-patch is branched from main, merged, and deployed within minutes without affecting ongoing feature work.
  • A code reviewer checks out a pull request branch locally to test it before merging, then switches back to their own work.

Key takeaways

  • Branches are lightweight pointers to commits — creating one is instant and does not copy files.
  • Use git switch -c to create and switch in one; git branch alone just creates and stays on the current branch.
  • HEAD always points to your current branch — switching updates both HEAD and your working directory to match that branch's tip.
  • Merging brings the changes from one branch into the branch you're currently on; fast-forward merges only happen when the target hasn't diverged.
  • Merge conflicts happen when both branches edit the same lines — resolve them manually, then commit to finish the merge.
  • Always check which branch you're on before committing or merging with git branch or git status.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.