A branch is just a movable label pointing at a commit — that is the whole implementation, and internalising it dissolves most branch anxiety. Creating one costs nothing, switching is instant, and deleting a merged one loses nothing.
Creating and switching #
$ git switch -c feature/toc # create and switch
$ git switch main # back to main
$ git branch feature/toc main # create without switching (classic)
$ git checkout -b feature/toc # the older equivalent
git switch arrived in git 2.23 to split the two jobs checkout had been doing — moving branches versus moving files. switch does branches only; restore does files only. Both are clearer than checkout's double life.
Seeing the branches #
$ git branch -vv
* main f3e2d1c [origin/main] fix: cache headers
feature/toc 9a8b7c wip: toc markup
$ git branch -a # includes remotes/origin/*
$ git branch --merged main # safe-to-delete list
-vv shows tracking relationships — which local branch follows which remote one — which is what you need before a push or a pull.
Where branches start #
A new branch grows from the current commit unless you say otherwise — and choosing the right starting point is half of branching well:
| Start from | Command | When |
|---|---|---|
| Current HEAD | git switch -c fix/x | The usual case |
| Fresh main | git switch -c fix/x origin/main | Starting from current production |
| A specific commit | git switch -c fix/x f3e2d1c | Bisect follow-ups, archaeology |
| A tag | git switch -c hotfix v1.4.0 | Production hotfixes |
Deleting and renaming #
$ git branch -d feature/toc # refuses if unmerged
$ git branch -D feature/toc # force — loses the label only
$ git branch -m feature/toc feature/table-of-contents
Deleting a branch deletes the label; the commits stay in the repository until garbage collection, which is why even -D accidents are recoverable through reflog. -d refusing to delete unmerged work is the safety valve — respect it unless you mean it.
The naming scheme that scales #
feature/toc new capability
fix/cache-headers bug repair
hotfix/v1.4.1 urgent production fix, cut from a tag
release/v1.5 stabilization before a release
Slashes create namespaces in every git tooling; prefixes sort naturally and say what the branch is before anyone reads its commits.
Uncommitted work that blocks a switch belongs to stash; parallel checkouts without switching are worktrees. The Git series continues.
