These are the git branch commands I actually type in a day, with no extra words: print the branch I am on, find a remote's default branch, jump back to the one I was just on, rename the current branch, and delete a branch both locally and on the remote.
git branch --show-current # which branch am I on?
git switch other-branch # move to an existing branch
git switch -c new-branch # create and move to a new one
git switch - # back to the previous branch
git branch -m better-name # rename the current branch
git branch -d feature # delete a merged local branch
git push origin --delete feature # delete the remote branchThe rest of this page is the detail behind each of those: the older forms still worth knowing, why git switch replaced git checkout for this work, and the gotchas that bite when you delete or rename.
A note on switch vs checkout up front, because it runs through everything below. git checkout does two unrelated jobs (moving between branches and restoring files), which is why it confuses people. Git 2.23 (August 2019) split those jobs into two focused commands: git switch for branches and git restore for files. Both are out of "experimental" and are what I reach for now. Every git checkout branch command still works, so nothing here breaks an old habit. I just lead with the clearer command.
Which branch am I on?
git branch --show-currentThis prints just the current branch name and nothing else, which is what you want in a script or a prompt. It landed in git 2.22 (June 2019), so on any reasonably current git it is the clean answer.
On an older git that predates --show-current, the portable fallback is:
git rev-parse --abbrev-ref HEADThat returns the branch name too, but with one quirk: in detached HEAD state (you checked out a tag or a raw commit, not a branch) it prints HEAD rather than a branch name, whereas git branch --show-current prints an empty line. Either is a fine signal that you are not on a branch; just know which you are testing for.
Plain git branch (no flags) lists your local branches and marks the current one with an asterisk, which is the human-eyeball version of the same question.
Switch branches, and create one in passing
git switch main # move to an existing branch
git switch -c new-feature # create new-feature and move to itgit switch -c new-feature is the modern replacement for git checkout -b new-feature: create a branch off your current HEAD and switch to it in one step. Use -C (capital) to reset the branch if it already exists, the same way checkout -B did.
To branch off a specific starting point rather than wherever you are now, name it:
git switch -c hotfix main # new branch hotfix, started from mainJump back to the previous branch
git switch -The bare - means "the branch I was on before this one," exactly like cd - jumps to your previous directory. It is the fastest way to bounce between a feature branch and main without typing either name. The older form git checkout - does the same thing and is fine on any git.
Find a remote's default branch
The default branch is the one a fresh clone checks out: historically master, now usually main on new repositories. When you script against "whatever the default is," do not hardcode the name. Ask git.
The offline answer, no network call, reads the symbolic ref your clone already stores:
git symbolic-ref refs/remotes/origin/HEAD --shortThat prints something like origin/main. Strip the origin/ prefix if you only want the branch name:
git symbolic-ref refs/remotes/origin/HEAD --short | sed 's@^origin/@@'One caveat: that local ref is set at clone time and is not automatically updated if the remote later changes its default. If it is missing or stale, re-point it from the remote:
git remote set-head origin --autoIf you would rather ask the remote directly (a network round trip, but always current), git remote show origin reports it in a HEAD branch: line:
git remote show origin
# look for: HEAD branch: mainTo pull just that value out for a script:
git remote show origin | sed -n '/HEAD branch/s/.*: //p'I reach for the symbolic-ref form by default (it is instant and offline) and fall back to remote show origin only when I suspect the local ref is wrong.
Rename a branch
git branch -m better-name # rename the branch you are on
git branch -m old-name better-name # rename a branch you are not on-m moves (renames) a branch. Renaming a branch that has already been pushed is the part people forget: the rename is purely local, so you then push the new name and delete the old one on the remote.
git push origin -u better-name # push the renamed branch, set upstream
git push origin --delete old-name # remove the old name from the remoteDelete a local branch
git branch -d feature # safe delete: refuses if not merged
git branch -D feature # force delete: removes it regardless-d is the safe form. It refuses to delete a branch that holds commits not yet merged into its upstream or the current branch, which is git stopping you from throwing work away by accident. When you are sure (you abandoned an experiment, say), -D forces it through. -D is shorthand for --delete --force.
You cannot delete the branch you are standing on. Switch off it first (git switch main), then delete.
Delete a remote branch
git push origin --delete featureThat deletes the branch named feature on the remote called origin. Deleting a remote branch and deleting your local copy are two separate acts: this command does nothing to your local feature branch, and git branch -d feature does nothing to the remote. To fully retire a branch you run both.
You will also see the older colon syntax, which still works:
git push origin :featureRead it as "push nothing into the remote ref feature," and pushing nothing into a ref deletes it. The --delete form does the same thing and says what it means, so I prefer it.
Deleting the remote branch does not clean up the stale remote-tracking ref (origin/feature) in other clones. Prune those with:
git fetch --pruneList branches, with detail
git branch # local branches, * marks current
git branch -a # local + remote-tracking branches
git branch -r # remote-tracking branches only
git branch -vv # each branch + last commit + its upstream and ahead/behindgit branch -vv is the one I lean on most when a branch's push is misbehaving: it shows each local branch's tracked upstream and whether you are ahead or behind, which is usually where the confusion is. If a branch is tracking the wrong upstream (or none), fix it in place without re-pushing:
git branch -u origin/main # set the current branch's upstream
git branch -u origin/main feature # set it for a branch you are not on-u is short for --set-upstream-to. This is the per-branch fix; git push -u origin feature does the same thing for a branch the first time you push it.
When it is time to clean up, these two filters tell you which branches are safe to delete and which still hold unmerged work:
git branch --merged # branches already merged into HEAD: safe to delete
git branch --no-merged # branches with commits not yet in HEAD: don't -d these--merged lists the branches reachable from your current HEAD (so git branch -d will accept them without complaint); --no-merged lists the ones that still carry work, which are exactly the branches -d refuses and -D would silently throw away. Pass a commit to either to test against something other than HEAD, for example git branch --merged main.
When you make a branching mistake (deleted too much, switched and lost track of work), the recovery path is git reflog and friends. See how to undo things in git for that whole toolkit.
FAQ
See also
- How to undo things in git: the recovery toolkit (restore, reset, revert, reflog) for when a branch operation goes sideways.
- Git tags: create, push, list, and delete: the tag equivalents of these branch commands, including annotated tags and deleting a tag on the remote.
- Git force push safely: --force vs --force-with-lease: the safe way to push a rewritten or renamed branch without clobbering a teammate's commits.
Sources
Authoritative references this article was fact-checked against.
- git-branch (official documentation)git-scm.com
- git-switch (official documentation)git-scm.com
- git-symbolic-ref (official documentation)git-scm.com
- git-remote (official documentation)git-scm.com





