git switch branch-name moves you to another branch. It arrived in Git 2.23, released August 16, 2019 (GitHub Blog, 2019), and older installs still need git checkout branch-name for the same job.
Git points HEAD at the target branch and rewrites the index and working tree to match, which is why you can hop between a feature branch and main without cloning the repo a second time.
A dirty working tree won’t necessarily stop you. According to the git-switch manual for Git 2.55.0, the operation aborts only when it would lose local changes, so uncommitted edits to files that are identical on both branches come along for the ride.
How do you switch to an existing branch in Git?

Run git switch branch-name inside the repository. On anything older than Git 2.23, git checkout branch-name does the same thing.
The git-switch manual says Git points HEAD at the target branch and then updates the index and the working tree to match it. Whatever you commit afterward lands on the tip of that branch.
A Git branch is just a movable pointer to a commit, so nothing gets copied during a switch. The files on disk change because Git rewrites them to the content of the target commit.
- Open a terminal in the repository folder.
- Run git branch to list local branches. An asterisk marks the current one.
- Run git switch feature-login, with your own branch name in place of feature-login.
- Run git status. The first line names the branch you are on.
git status also lists any modified files that traveled with you.
Jump back to the previous branch
If you bounce between main and a feature branch all day, type git switch – and you land on whatever branch you were on before.
The manual treats the dash as shorthand for @{-1}. @{-2} goes back two switches, and switches made with git checkout count too.
Git switch vs git checkout: which command to use
On Git 2.23 or newer, use git switch. Keep git checkout for old installs and for scripts that might run on them.
Git 2.23 shipped on August 16, 2019 with git switch and git restore, both marked experimental (GitHub Blog, 2019). The idea was to split the overloaded git checkout into one command for changing branches and another for changing files.
The git-switch manual for Git 2.55.0 (June 2026) no longer carries the experimental label.
| Feature | git switch | git checkout |
|---|---|---|
| Purpose | Branches only | Branches and files |
| Create and switch | git switch -c new-branch | git checkout -b new-branch |
| Commit or tag target | Requires –detach | Detaches automatically |
| Restore a file | No, use git restore | Yes, git checkout — file |
| Available since | Git 2.23 | Every version |
The git checkout command still works fine, and its manual now points to git switch and git restore under See Also.
Ambiguity is the real reason to move over. Checkout has to guess whether an argument is a branch or a file, and the manual’s own example is a branch named hello.c that gets mistaken for the file.
Shared scripts are the one place I’d leave checkout alone. A CI image running Git older than 2.23 has no switch subcommand at all, and git –version answers that in a second.
How to create a new branch and switch to it in one step
git switch -c new-branch creates the branch at your current commit and switches to it in one go. With checkout it’s git checkout -b new-branch.
The manual calls -c the transactional equivalent of git branch followed by git switch, meaning that if the switch fails, the branch isn’t created or reset.
Starting from a specific commit or tag
To start from a commit, git switch -c fixup HEAD~3 begins the branch three commits behind the current one (that’s the git-switch manual’s own example). For a tag, git switch -c speed-up-spinlocks v2.6.35 comes straight from the Git user manual. And for another branch you’d write git switch -c hotfix main.
Leave the start point out and Git uses the commit HEAD points at right now.
Creating a branch without switching
git branch new-branch creates the pointer and leaves you where you are. Handy when you want to mark a spot and keep working.
Branch creation has its own set of options, covered in this guide to creating a new branch in Git.
When the branch name is already taken
- -c refuses and reports that the branch exists
- -C (checkout -B) resets the branch to the start point
- After a reset, the old tip no longer belongs to that branch
Only use -C when you actually mean to move the pointer.
How to switch to a remote branch
Fetch first, then switch using the plain branch name. git fetch origin followed by git switch feature-search creates a local feature-search branch that tracks origin/feature-search.
That shortcut is the –guess behavior, which is on by default. Per the git-switch manual, it only kicks in when exactly one remote has a remote-tracking branch with that name.
The fetch matters because the guess reads refs your clone has already stored. A fetch only updates those remote-tracking refs and leaves your working tree untouched.
A branch someone pushed an hour ago stays invisible until you fetch. git branch -r shows what your clone knows about, so look there before blaming a typo.
If a local copy already exists, git switch uses it and never asks the remote. Merge or pull to catch up.
Naming the local branch yourself
git switch -c feature-search –track origin/feature-search spells out what the guess does silently. Drop -c and run git switch –track origin/feature-search, and Git derives the local name by stripping the remote prefix, so origin/hack becomes hack.
Want a different local name? git switch -c search-wip origin/feature-search works, and tracking gets set up automatically when the start point is a remote-tracking branch (git-branch manual, default branch.autoSetupMerge).
When several remotes share a branch name
Say two remotes both hold feature-search. The guess stops working at that point. Set checkout.defaultRemote to your origin remote and Git uses it to break the tie.
- git config –global checkout.defaultRemote origin
- git switch –no-guess turns the shortcut off for one command
- checkout.guess set to false turns it off everywhere
What happens to uncommitted changes when you switch branches?
Git carries uncommitted changes to the new branch when the files involved are identical on both branches. When a change would be overwritten, it refuses the switch.
The git-switch manual says the switch doesn’t need a clean index or working tree. It aborts only if a local change would be lost.
Say you edited README.md. If the target branch holds the same README.md, your edit comes along.
If the target branch changed that file, Git stops and prints a message like “Your local changes to the following files would be overwritten by checkout”, then lists the files and hints at a commit or stash.
| Option | Command | Where the changes end up | Main risk |
|---|---|---|---|
| Commit | git add, git commit, then switch | A commit on the branch you leave | Half-finished work in history |
| Stash | git stash, switch, git stash pop | The stash list, then back in the working tree | Forgotten entries; untracked files stay behind |
| Carry over | git switch -m branch-name | Reapplied on the target branch, unstaged | Conflicts land in the stash list |
| Discard | git switch –discard-changes branch-name | Nowhere | The edits are gone |
I’d start with a stash or a commit. -m earns its place when only a few lines overlap, and discarding is for edits you’d delete anyway.
Stashing before you switch
Run git stash, or git stash -u if untracked files need to travel with it. Then git switch other-branch, do the urgent work and commit it. When you’re done, switch back and run git stash pop.
That sequence extends the interrupted-workflow example in the git-stash manual, which stashes, makes the urgent fix and pops on a single branch. How git stash stores entries matters when a pop fails, because a pop that hits conflicts keeps the entry in the list instead of dropping it.
If the branch has moved far enough that a pop conflicts every time, git stash branch new-branch recreates the stash on top of the commit it was made from.
Carrying changes with –merge
git switch -m branch-name stashes the conflicting changes, switches, then reapplies them. That’s how the 2.55.0 manual describes it.
Older manuals called -m a three-way merge between the current branch, your working tree and the new branch, so the wording depends on your Git version. Either way you end up with your edits on the target branch, unstaged.
- No overlap with the branch differences: the switch runs without stashing
- Overlap: changes are stashed, then reapplied after the switch
- Conflict on reapply: the entry stays in the stash list until you run git stash drop
Clear the conflict markers the same way you would when resolving merge conflicts in Git, then drop the stash entry.
Discarding changes on purpose
Only do this with throwaway edits.
git switch –discard-changes branch-name restores both the index and the working tree to match the target branch, and -f is an alias for it.
Checkout behaves a little differently. The git-checkout manual says git checkout -f also throws away untracked files that are in the way, while the git-switch manual documents -f only as an alias of –discard-changes and says nothing about untracked files.
How to switch to a commit or tag with a detached HEAD
Run git switch –detach followed by a commit hash or tag name. HEAD then points straight at that commit instead of at a branch.
The manual’s own example is git switch –detach HEAD~3, which checks out the commit three steps back. Leave the flag out and Git answers with an error saying it expected a branch.
Switching to a tag puts you in the same state, since a Git tag marks one specific commit.
That state, a detached HEAD, is meant for looking around and for experiments you can throw away, according to the git-switch manual.
Keeping commits made while detached
Commits made in this state belong to no branch.
Once you switch away, nothing refers to them, and the git-checkout manual says routine garbage collection will eventually delete them. You can create a reference before that happens. git switch -c foo makes a branch and attaches HEAD to it, git branch foo makes the branch while HEAD stays detached, and git tag foo marks the commit, also leaving HEAD detached.
If you already moved away, the reflog still has them. Entries that are no longer reachable from the current tip expire after 30 days by default (git-gc manual, as of Git 2.56.0), so the commits stay recoverable for that long unless you changed gc.reflogExpireUnreachable.
Run git reflog -2 HEAD (or git log -g -2 HEAD) to list the last two positions HEAD held, copy the hash, then run git switch -c rescued-work with that hash.
Returning to a branch
git switch main puts HEAD back on a branch. git switch – takes you to whatever you were on before the detach, and Git prints that hint itself when you detach.
- The hint is controlled by advice.detachedHead
- Setting it to false silences the message, not the state
Why does git refuse to switch branches, and how do you fix it?
Most refusals trace back to conflicting local changes, a name Git can’t resolve, or a branch another worktree already holds. The remaining two causes are passing a commit or tag without –detach and running a Git older than 2.23.
| Message | Cause | Fix |
|---|---|---|
| error: Your local changes to the following files would be overwritten by checkout | Uncommitted edits touch files that differ on the target branch | Commit, stash, or use -m |
| fatal: invalid reference (git switch) or error: pathspec did not match any file(s) known to git (git checkout) | Misspelled name, or a remote branch that was never fetched | Check git branch -a, run git fetch |
| fatal: ‘name’ is already used by worktree at ‘path’ | Another worktree has that branch checked out | Switch that worktree to another branch, or pick a different one |
| fatal: a branch is expected, got commit | git switch received a commit or tag | Add –detach |
| git: ‘switch’ is not a git command | Git is older than 2.23 | Upgrade Git, or use git checkout |
The missing-subcommand error is the easiest one to fix for good, and installing a current Git release takes a few minutes. Older Git releases word the worktree message as “is already checked out at” instead.
There’s a worktree override too. –ignore-other-worktrees makes Git check the branch out anyway, so the ref can be held by more than one worktree (git-switch manual). I’d avoid it. A commit in one worktree leaves the other sitting behind the branch tip, and git worktree list shows where the branch is held.
A refused switch is almost always protecting uncommitted work. Try a commit or a stash before you reach for force.
Switching Branches in Git FAQ
How do I switch branches in VS Code?
Select the branch name in the Status Bar, or run Git: Checkout to from the Command Palette. The list shows local, remote and recent branches (VS Code documentation).
Can I switch branches in GitHub Desktop?
Yes. Click Current Branch in the repository bar, then pick the branch.
With uncommitted changes, a Switch Branch window asks whether to leave them on the current branch or bring them to the new one (GitHub Docs).
Does switching branches delete my commits?
No. Commits stay on the branch you left, because a switch only moves HEAD and rewrites the working files.
Uncommitted edits are the only thing at risk, and Git aborts rather than overwrite them.
Which name do I use, main or master?
Whichever one the repository has, since each repo sets its own default branch. Run git branch to list what exists, then git switch main or git switch master.
What does git switch –orphan do?
It creates a new unborn branch and removes all tracked files from the working tree, according to the git-switch manual.
The first commit on it has no parent, so it starts a history disconnected from every other branch.
Does git switch update submodules?
Not by default. Add –recurse-submodules and Git updates active submodules to the commit the superproject records.
The manual notes that this detaches HEAD inside each submodule.
Keeping Work Safe While Switching Branches in Git
Commit unfinished work before switching branches in Git, and stash only for interruptions that end the same day. A commit stays on its branch until the branch is deleted, while the git-stash manual keeps the latest stash in refs/stash and older entries in that ref’s reflog.
The git-gc manual expires reflog entries older than 90 days by default, and entries not reachable from the current tip after 30 days. Its gc.refs/stash.reflogExpire pattern form sets a separate limit for stashes only, so a forgotten stash is not permanent storage (manual checked October 2, 2026).
Ranked by how long they last, a commit comes first and is the one to use for anything you want to keep. A stash with a message (git stash push -m) suits short detours. -m and –discard-changes go last.
The price of committing first is a work-in-progress commit sitting on the branch.
With the work committed, the natural next move is merging two branches in Git.
- VS Code Extensions That Are Actually Worth Installing - October 13, 2026
- Google Play App Signing Explained - October 11, 2026
- 5 Best NinjaOne Alternatives for Focused Endpoint Management - October 10, 2026



