open atlas
↑ Back to track
Git, from zero to senior GIT · 03 · 02

Create and switch branches

git switch moves HEAD between branches and git switch -c creates one in a single step. git branch creates without switching, -d/-D delete, -m renames, -vv lists with tracking. Uncommitted changes can block a switch; checking out a commit detaches HEAD.

GIT Junior ◷ 16 min
Level
FoundationsJuniorMiddleSenior

You now know a branch is a pointer and HEAD names the current one. The everyday job is moving that pointer around: make a new branch for a feature, hop onto it, hop back to main, throw the branch away when you are done. For years the one verb for all of this was the overloaded git checkout, which also restored files — a frequent source of “wait, did I just switch branches or discard my work?” Git 2.23 split it into two clearer verbs.

By the end of this lesson you will be able to create, switch, list, rename, and delete branches with the modern commands, and recognise the older checkout forms you will still see everywhere.

Goal

After this lesson you can create and switch branches with git switch / git switch -c, create without switching using git branch, delete with -d versus -D, rename with -m, list with -vv, map these onto the older git checkout forms, and explain why an uncommitted change can block a switch.

1

git switch moves HEAD to an existing branch; git switch -c creates a new branch and moves there in one step. This is the modern, purpose-built verb (git 2.23+):

git switch main              # move onto an existing branch
git switch -c feature-login  # create 'feature-login' at the current commit, then switch to it

-c is “create”. The new branch starts pointing at wherever HEAD is right now, so git switch -c is the everyday “start a feature off the current state” command. After it, HEAD → feature-login → <current commit>.

2

git branch <name> creates a branch without switching to it. Sometimes you want to bookmark the current commit but keep working where you are:

git branch hotfix      # create 'hotfix' at the current commit; HEAD does NOT move
git branch             # list local branches; * marks the current one
git branch -vv         # list with each branch's tip commit and its upstream (tracking) branch

git branch alone is the create-or-list verb; it never changes which branch you are on. -vv is the listing you reach for when you need to see what each branch tracks on the remote.

3

Delete with -d (safe) or -D (force); rename with -m. Cleaning up pointers:

git branch -d feature-login   # delete, but REFUSE if it has unmerged commits
git branch -D feature-login   # force-delete even if unmerged (you may lose those commits)
git branch -m old-name new-name   # rename a branch

-d is the guardrail: it only deletes a branch whose commits are already reachable from somewhere else, so you cannot accidentally orphan unmerged work. -D overrides that check — reach for it only when you genuinely want to discard the branch’s unique commits.

Why this works

Why split checkout into switch and restore? The old git checkout did two unrelated jobs: moving HEAD between branches and overwriting files in your working tree from a commit. That overlap caused real accidents — git checkout somefile silently discarded uncommitted edits to that file, while git checkout somebranch switched branches, and a typo could turn one into the other. Git 2.23 introduced git switch (change branch) and git restore (change files) so each verb does exactly one thing. checkout still works and is everywhere in tutorials, but the split verbs are safer.

4

The older git checkout forms still appear everywhere — know the mapping. They are equivalent for branch work:

git checkout main             # == git switch main
git checkout -b feature       # == git switch -c feature
git checkout <commit-id>      # detaches HEAD onto that commit (no branch)

That last one is how you land in detached HEAD: checking out a commit (or tag) instead of a branch points HEAD straight at the commit. Git prints a clear warning and tells you to make a branch if you want to keep any commits you make there. To leave, just switch back to a real branch: git switch main. The modern equivalent for inspecting a commit is git switch --detach <commit-id>.

5

Uncommitted changes can block a switch — and that is a feature. If you have local edits that the target branch would overwrite, git refuses rather than silently clobbering them:

git switch other-branch
# error: Your local changes to the following files would be
# overwritten by checkout: app.js
# Please commit your changes or stash them before you switch.

Your options: commit them, stash them (git stash, set aside for later), or discard them. Git protects work it cannot safely carry across the switch. If the edits do not conflict with differences between the branches, git carries them along and the switch succeeds.

Worked example

A feature from start to cleanup.

You are on main and want to build a login form without disturbing main:

git switch -c feature-login   # create + switch; HEAD → feature-login → (main's commit)
# ...edit files...
git commit -m "Add login form"   # feature-login advances; main untouched

You finish, get it merged into main, then tidy up:

git switch main               # HEAD → main
git branch -d feature-login   # safe-delete; succeeds because it is merged

Now suppose instead you abandoned the feature without merging and try the same delete:

git branch -d feature-login
# error: The branch 'feature-login' is not fully merged.

Git refuses, because -d will not orphan unmerged commits. If you truly want it gone, git branch -D feature-login forces it — and those commits become unreachable. That single-letter difference, -d versus -D, is the line between a safe cleanup and discarding work.

Common mistake

A classic trap: running git checkout <commit-id> to “look at” an old version, committing a quick fix there, then switching back — and discovering the fix vanished. Those commits were made in detached HEAD, attached to no branch, so switching away orphaned them. The fix is to create a branch before leaving: git switch -c rescue-fix turns the detached commits into a real branch. If you already left, git reflog can still find the orphaned commit ID for a while.

Check yourself
Quiz

What is the difference between git branch -d and git branch -D?

Recap

git switch <branch> moves HEAD onto an existing branch; git switch -c <name> creates a branch at the current commit and switches to it in one step. git branch <name> creates without switching, git branch -vv lists branches with their tips and upstreams, -d safely deletes (refusing unmerged branches), -D force-deletes, and -m renames. These map onto the older git checkout / git checkout -b, and checking out a commit lands you in detached HEAD. Uncommitted changes that a switch would overwrite block the switch on purpose — commit or stash first. Next you will take two branches that have diverged and join them back together with git merge.

Practice

Start at the top. Tasks go easiest → hardest: recall a fact, apply it to a case, then a senior-level stretch. Open one, attempt it, then reveal.

recallapplystretch0 of 4 done

Something unclear?

Ask a question about this lesson. Questions are anonymous and go straight to the author to make the lesson better.

shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.