Branching is one of Git's most powerful features. A branch lets you diverge from the main line of development, work on a feature or fix in isolation, and merge your changes back when ready — without disrupting your teammates.
What is a Branch?
In Git, a branch is simply a lightweight pointer to a commit. When you commit, the current branch pointer moves forward to the new commit automatically. Creating a branch costs almost nothing — it just creates a new 41-byte file containing a SHA-1 hash.
The special pointer HEAD points to the branch you are currently on (or directly to a commit in "detached HEAD" state).
Core Branch Commands
# List all branches (* marks current branch)
git branch
# Create a new branch
git branch feature/user-auth
# Switch to a branch
git switch feature/user-auth
# Create AND switch in one command (preferred)
git switch -c feature/user-auth
# Rename current branch
git branch -m new-name
# Delete a merged branch (safe)
git branch -d feature/user-auth
# Delete a branch regardless of merge status (force)
git branch -D feature/user-auth
Merging
Merging integrates the history of one branch into another. You always merge into the currently checked out branch:
git switch main
git merge feature/user-auth
Fast-Forward Merge
If the target branch has not diverged from the source branch (no new commits on main since the branch was created), Git performs a fast-forward merge: it simply moves the branch pointer forward. No merge commit is created — the history is linear.
Before:
main: A -- B
feature: C -- D
After fast-forward merge into main:
main: A -- B -- C -- D
Three-Way Merge
If both branches have diverged (new commits exist on both), Git performs a three-way merge: it finds the common ancestor commit, compares both branch tips, and creates a new merge commit with two parents.
Before:
main: A -- B -- E
feature: C -- D
After three-way merge:
main: A -- B -- E -- M (M is the merge commit)
/
feature: C -- D
Use git merge --no-ff feature/user-auth to force a merge commit even when a fast-forward is possible — this preserves a record that a feature branch existed.
Merge Conflicts
A merge conflict occurs when the same lines were changed differently in both branches. Git cannot decide which version to keep — it needs you to resolve it.
Git marks the conflict in the file:
<<<<<<< HEAD
const timeout = 5000;
=======
const timeout = 10000;
>>>>>>> feature/user-auth
To resolve:
- Open each conflicted file (shown in
git status) - Edit the file to the desired final state (remove the conflict markers)
- Stage the resolved file:
git add src/config.ts - Complete the merge:
git commit
Most editors (VS Code, IntelliJ) have built-in merge conflict UI that highlights the sections and provides one-click accept buttons — prefer that over editing raw conflict markers.
Viewing Branches Graphically
git log --oneline --graph --all
This renders a text-based graph of all branches and merges — invaluable for understanding a complex repository history.
Branching Best Practices
- Keep branches short-lived — the longer a branch lives without merging, the more merge debt accumulates.
- Name branches descriptively:
feature/user-auth,fix/null-pointer-login,chore/update-dependencies. - Delete branches after merging — they leave clutter and can cause confusion.
- Before merging a feature branch, update it from main (
git merge mainorgit rebase main) to resolve conflicts in your branch — not in main.