Create, switch, rename, delete
Intermediate Git CLI VS Code UI IntelliJ UI GitLab UI GitHub UI
Why this matters
These four operations are the branch vocabulary you will use daily. They are simple, but two of them have a sharp edge (switching with uncommitted edits, deleting an unmerged branch), and older instructions on the internet use git checkout for everything, which confuses beginners. This lesson gives you the modern commands, the edges, and the translation.
Create and switch
$ git switch -c docs/12-windows-install-stepsSwitched to a new branch 'docs/12-windows-install-steps'-c means "create". The branch starts at the commit you were on (so update main first), and HEAD moves to it. To start from somewhere else without switching there first: git switch -c hotfix/23-region-name v1.2.0.
Switching to an existing branch:
$ git switch mainSwitched to branch 'main'
Your branch is up to date with 'origin/main'.git switch - goes back to the previous branch, like cd -. A typo gets a clear refusal:
$ git switch nopefatal: invalid reference: nopeAnd a switch that would overwrite uncommitted edits is refused too — commit or stash first (lesson 5.7):
error: Your local changes to the following files would be overwritten by checkout:
README.md
Please commit your changes or stash them before you switch branches.
AbortingEdits that do not touch files differing between the branches simply come along; that is convenient when you realize you started editing on the wrong branch before committing.
Rename
$ git branch -m docs/12-windows-install-steps docs/12-windows-steps
$ git branch* docs/12-windows-steps
main-m for "move". With one argument it renames the current branch. If the old name was already pushed, the remote still has it: push the new name (git push -u origin docs/12-windows-steps) and delete the old (git push origin --delete docs/12-windows-install-steps), or, better, rename before the first push.
Delete
$ git branch -d docs/33-faq-windowsDeleted branch docs/33-faq-windows (was 3008743).Lowercase -d is the safe delete: Git checks that the branch's commits are reachable from another branch (merged) and refuses otherwise:
$ git branch -d feature/21-difficulty-filtererror: the branch 'feature/21-difficulty-filter' is not fully merged
hint: If you are sure you want to delete it, run 'git branch -D feature/21-difficulty-filter'
hint: Disable this message with "git config set advice.forceDeleteBranch false"-D deletes anyway. The refusal is worth a look every time: if the branch was merged by squash on GitLab, Git cannot see that (the squash commit is different from the branch's commits) and -D is fine; if the branch simply was never merged, -D abandons the work. git branch --merged and --no-merged list which is which:
$ git branch --no-merged fix/15-empty-distanceYou cannot delete the branch you are on; switch to main first. Remote branches are deleted separately (lesson 6.8).
The old way: git checkout
Before Git 2.23, one command did both jobs and more:
| Old | New | Meaning |
|---|---|---|
git checkout <branch> |
git switch <branch> |
switch |
git checkout -b <branch> |
git switch -c <branch> |
create and switch |
git checkout -- <file> |
git restore <file> |
discard edits to a file |
git checkout <commit> |
git switch --detach <commit> |
look at an old commit (detached HEAD) |
git checkout still works and appears in most older tutorials; the new commands exist because the old one silently did very different things depending on whether its argument was a branch or a file. Read checkout in a tutorial as whichever of the two new commands fits.
In the tools
| Task | Command |
|---|---|
| Create and switch | git switch -c <name> (git switch -c <name> <start> to start elsewhere) |
| Switch | git switch <name>; git switch - for the previous one |
| List | git branch, git branch -a, git branch -vv |
| Rename | git branch -m <old> <new> |
| Delete merged | git branch -d <name> |
| Delete unmerged | git branch -D <name> |
- Switch or create: click the branch name in the status bar (bottom left). The list shows local and remote branches; pick one to switch, or choose + Create new branch… and type the name. Fallback: Command Palette → Git: Checkout to… / Git: Create Branch….
- Create from a specific point: Git: Create Branch From… asks for the starting branch, tag or commit.
- Rename: Command Palette → Git: Rename Branch….
- Delete: Command Palette → Git: Delete Branch…; VS Code warns if the branch is not merged.
- Uncommitted edits: VS Code switches if it can; otherwise it offers to stash.
- Branches popup: click the branch name in the status bar (bottom right) or Git → Branches… (Ctrl+Shift+
</kbd> / <kbd>⌃⇧). - + New Branch creates from the current commit (untick "Checkout branch" to create without switching). Right-click any branch or commit in the Log → New Branch from Here… to start elsewhere.
- Switch: select a branch → Checkout. For a remote branch, IntelliJ creates the local tracking branch for you.
- Rename and Delete are in the same right-click menu; IntelliJ warns about unmerged commits and offers to restore a deleted branch for a while.
- Uncommitted edits that conflict: IntelliJ offers Smart checkout (shelve, switch, unshelve).
Branches created on the web exist only on the remote until you fetch: Code → Branches → New branch, choose the name and the source (branch or tag). From an issue, Create merge request → Create branch creates a branch named from the issue. Code → Branches also deletes branches (the bin icon), and lists merged and stale ones. Locally, git fetch then git switch <name> picks up a web-created branch as a tracking branch.
On the repository page, open the branch dropdown, type a new name, and click Create branch … from main. From an issue, the Development panel on the right offers Create a branch. The Branches page (the branch count link) lists, filters and deletes branches. Same as GitLab: fetch, then switch locally.
Common mistakes
- Creating a branch while on another feature branch. It inherits that branch's commits. Check
git status's first line beforeswitch -c. -Dby reflex. Read the refusal;--no-mergedtells you what you would lose.- Renaming after pushing and ending up with two remote branches. Rename first, or clean up the old remote name.
- Reading
git checkoutin a tutorial as something dangerous. It is just the old spelling of switch or restore.
Try it yourself
Goal: run the full create → switch → rename → delete cycle, including one refused delete.
- From an up-to-date
main:git switch -c docs/practice-cycle. - Make an empty commit on it, then
git switch main, thengit branch -d docs/practice-cycleand read the refusal. - Rename it anyway:
git branch -m docs/practice-cycle docs/practice-renamed; list withgit branch --no-merged. - Delete it with
-D.
Expected result: step 2 prints "not fully merged"; step 3 shows the renamed branch as unmerged; step 4 prints "Deleted branch docs/practice-renamed (was …)".
Show solution
The refusal protected the empty commit, which existed on no other branch. -D said "I know", and the commit is now unreferenced (still in the reflog for a while). The same sequence with a merged branch would have deleted silently with -d.