Branches
A branch is an independent line of work. You create one to build a feature, fix a bug or try an idea without disturbing the main code; when it's ready, you merge it back. In Git, branches are instant and cost almost nothing, so you'll use them for nearly everything.
Why branch?
Imagine Sam is halfway through reorganising the recipe collection when someone reports a typo that needs fixing right away. Without branches, the half-finished reorganisation and the urgent fix get tangled together. With branches, the reorganisation lives on its own branch; Sam switches back to main, fixes the typo, and returns to the reorganisation later. Teams use the same idea at scale: every feature or fix is developed on its own branch and reviewed before it joins main.
Listing branches
git branch
* main
A new repository has one branch, main. The * marks the current branch. -v adds each branch's latest commit:
git branch -v
* main 90c0089 Add omelette recipe
Creating a branch
git branch desserts git branch
desserts * main
git branch <name> creates a branch pointing at the current commit — but it doesn't switch to it; you're still on main. Usually you want to create and switch in one go, which is git switch -c (next lesson).
What a branch really is
A branch is nothing more than a name for a commit. Git stores it as a tiny file containing a hash:
cat .git/refs/heads/desserts git rev-parse main
90c00895dd5f3596c58ac005e17872f41039efcb 90c00895dd5f3596c58ac005e17872f41039efcb
Both branches point at the same commit right now. When you commit on a branch, only that branch's label moves forward to the new commit; the others stay where they are:
main, desserts main
│ │
A ◀── B ◀───┘ commit on desserts A ◀── B ◀── C
─────────────────▶ │
desserts
That's why creating a branch is instant, even in a huge project: nothing is copied.
Branching from another point
Add a commit or another branch name to start the new branch somewhere other than where you are:
git branch first-draft HEAD~1 git branch -v
desserts 90c0089 Add omelette recipe first-draft c4f5e47 Add pancake recipe * main 90c0089 Add omelette recipe
Renaming
git branch -m first-draft archive/first-draft git branch
archive/first-draft desserts * main
git branch -m new-name with one name renames the current branch.
Deleting
-d deletes a branch, but only if its commits are safely merged somewhere. Git refuses otherwise, to protect unmerged work:
git branch -d desserts
error: The branch 'desserts' is not fully merged. If you are sure you want to delete it, run 'git branch -D desserts'.
If you really want to throw the work away, -D forces it. (Deleted by mistake? The reflog can bring it back; lesson 20.) A fully merged branch deletes without fuss:
git branch -d archive/first-draft
Deleted branch archive/first-draft (was c4f5e47).
Deleting a branch only removes the label. Commits that are part of another branch remain in history.
Naming branches
Branch names can contain letters, numbers, -, _, . and /, but no spaces. Most teams adopt a pattern that says what the branch is for:
| Pattern | Example |
|---|---|
feature/… | feature/gift-cards |
fix/… or bugfix/… | fix/checkout-total |
| With an issue number | 142-empty-basket-crash |
| With your name | sam/try-new-layout |
Keep names short, lowercase and descriptive. The slash is just part of the name, but many tools display such branches as folders.
Useful listings
| Command | Lists |
|---|---|
git branch -a | Local and remote-tracking branches (lesson 35) |
git branch --merged | Branches already merged into the current one — safe to delete |
git branch --no-merged | Branches with work not yet merged |
git branch --sort=-committerdate | Most recently updated first |
git branch --list "fix/*" | Branches matching a pattern |
git branch --no-merged
desserts
Try it yourself
Create three branches from main, commit something on one of them, then use git branch -v, --merged and --no-merged to see which is which. Delete the two that are merged with -d.