Skip to content
masterclass Buddy

Git · Command

git branch

git branch manages branches. It can list, create, rename, copy and delete them, and it can set or change the upstream branch each one follows.

Last updated

How it works

In Git, a branch is a named ref under refs/heads that points to a commit. With no name argument, git branch lists refs and accepts filters such as --merged, --contains, --sort and --format. Given a name, it creates a new ref at HEAD or at a start point you choose. A start point can be a branch, tag or commit ID, and A...B uses the merge base of A and B. If the start point is a remote-tracking branch, branch.<name>.remote and branch.<name>.merge are written by default, which lets pull and status know the upstream. Other flags rename, copy or delete refs, and renames and copies carry the branch's config and reflog with them.

Syntax

git branch [--list] [-r|-a] [<pattern>...]
git branch [--track[=(direct|inherit)] | --no-track] [-f] <branch-name> [<start-point>]
git branch (--set-upstream-to=<upstream>|-u <upstream>) [<branch-name>]
git branch (-m|-M) [<old-branch>] <new-branch>
git branch (-c|-C) [<old-branch>] <new-branch>
git branch (-d|-D) [-r] <branch-name>...

Parameters

NameTypeDescription
<branch-name>string (ref name)Name of the branch to create or delete. It must pass the checks in git check-ref-format.
<start-point>commit-ishThe commit the new branch will point to, given as a branch name, commit ID or tag. If left out, HEAD is used.
<old-branch>stringAn existing branch to rename or copy. If left out, the current branch is used.
<new-branch>stringThe new name used by a rename or copy. It has the same naming rules as <branch-name>.
<pattern>shell globUsed with --list to show only matching branches. A branch is shown if it matches any of the patterns.
<commit>commit-ishThe commit used by --merged, --no-merged, --contains and --no-contains. Defaults to HEAD.
<upstream>stringThe branch to set as upstream with -u or --set-upstream-to.

Key points

  • With no arguments, git branch lists local branches and marks the one you are on. Add -r to list only remote-tracking branches, or -a to list local and remote-tracking branches together.
  • -d deletes a branch only if its work is already in its upstream, or in HEAD when it has no upstream. -D (--delete --force) deletes it whether or not it has been merged.
  • -m renames a branch and -c copies one. Both bring the branch's configuration and reflog along. Use the uppercase forms -M or -C to overwrite a branch that already has the new name.
  • Upstream tracking set with --track or -u is what lets git status and git branch -v show how far ahead or behind a branch is, and it gives a plain git pull its default source.
  • --merged lists branches whose tips can be reached from the given commit, so it is the usual way to find branches that are safe to clean up.
  • You can pass --sort more than once, and the last key you give is the primary one. Keys use git for-each-ref field names, for example --sort=-committerdate to show the most recently changed branches first.
  • -vv adds each branch's upstream name and linked worktree path to the verbose listing. --show-current prints only the current branch name, which is handy in scripts.

Common mistakes

  • If you run git branch 'feat-*' without --list, Git can treat the glob as the name of a new branch to create instead of a filter.
  • Creating a branch does not move you onto it, so your next commit still goes to the old branch. Use git switch, or git switch -c to create and switch in one step.
  • git branch -f cannot reset a branch that is checked out in another linked worktree, even though -f is meant to force the change.
  • The old --set-upstream option no longer works. Use --track when creating a branch, or -u / --set-upstream-to for an existing one.

Example: Feature-branch lifecycle with git branch

#!/usr/bin/env bash
set -euo pipefail

# Create a branch from the remote main, tracking it
git fetch origin
git branch --track feature/login origin/main
git switch feature/login

# Inspect: current branch, verbose list with upstreams
git branch --show-current
git branch -vv

# List only matching branches, newest first
git branch --list 'feature/*' --sort=-committerdate

# Rename the branch and point it at a new upstream
git branch -m feature/login feature/auth-login
git branch -u origin/main feature/auth-login

# After merging into main, clean up
git switch main
git branch --merged main
git branch -d feature/auth-login

When to use it

Start work from a release tag

Create a branch at a tag such as v2.6.14 to fix something in that release without touching your current branch.

Prune merged topic branches

After a release, run git branch --merged main to list local branches that are already merged into main, then remove them with -d.

Find branches affected by a bad commit

Before rebasing or amending a commit, run git branch --contains <sha> to find every branch that includes it and will need attention.

Fix tracking after a remote rename

Use git branch -u <remote>/<branch> to point an existing local branch at a new upstream so pull and status work again.

Interview questions

QIf you create a local branch from origin/main, how does Git know where git pull should pull from?

When the start point is a remote-tracking branch, git branch records branch.<name>.remote and branch.<name>.merge in the config. This happens because branch.autoSetupMerge defaults to true. You can change this per command with --track or --no-track, or later with --set-upstream-to.

Follow-up: What is the difference between --track=direct and --track=inherit? With direct, the start-point branch itself becomes the upstream. With inherit, the new branch copies the start point's own upstream configuration.

QHow do --merged and --contains differ?

--merged <commit> lists branches whose tips can be reached from that commit, meaning their work is already included in it. --contains <commit> lists branches whose tips descend from that commit, meaning the branch includes it. Both default to HEAD when no commit is given, and both turn on list mode.

Follow-up: How are several --merged and --no-merged filters combined? A ref is shown only if it can be reached from at least one --merged commit and from none of the --no-merged commits.

QDoes git branch -d -r origin/foo delete foo on the server?

No. It only deletes your local remote-tracking ref. The manual says this is only worth doing if the branch no longer exists on the remote, or if fetch has been set up not to fetch it.

Follow-up: How do you clean up all stale remote-tracking branches at once? Use the prune subcommand of git remote, as the git-branch manual suggests.

  • git switch
  • git checkout
  • git merge
  • git for-each-ref
  • git check-ref-format
  • git remote
  • git fetch
  • git pull

Source: Git - git-branch Documentation. Checked 2026-11-02.