A branch in Git is the cheapest operation you can perform. In centralized VCS like SVN, a branch means copying the entire project. In Git, it means creating a file with one line.
What a branch is, physically
cat .git/refs/heads/main
# a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
One commit SHA. That's it. From that commit, the full history
reachable from this branch comes via the parent chain.
Creating a branch means creating a file with the current commit's SHA. Moving a branch means rewriting that file. Deleting a branch means deleting the file. That is why branch/checkout/delete are instant even on a repository with a million commits.
Basic operations
git branch # list local branches
git branch -a # + remote branches
git branch -v # + last commit of each branch
git branch feature # create branch feature from HEAD
git branch feature main # create feature from main
git switch feature # switch to branch (new command)
git checkout feature # switch to branch (old, still works)
git switch -c feature # create and switch
git branch -d feature # delete (only if merged)
git branch -D feature # force delete
git branch -m old new # rename
Since Git 2.23 (2019) there are two specialized commands replacing
the overloaded checkout: git switch for branches and git restore
for files. If you are just starting out, use them. They are clearer
and safer.
HEAD and the active branch
When you switch to a branch, Git rewrites .git/HEAD:
ref: refs/heads/feature
Every new commit will now advance the feature branch. HEAD is
a pointer to a pointer.
If HEAD contains a bare SHA (no ref: prefix), you are in detached HEAD
state. This happens with git checkout <sha> or git checkout <tag>.
Commits made in this state are not held by any branch. To avoid losing
them, run git switch -c rescue to create a branch from the current HEAD.
Tracking branches
A local branch can track a remote branch:
git branch -u origin/main main # bind main to origin/main
git push -u origin feature # push and bind
After that, git status shows ahead/behind counts, and git pull
and git push with no arguments know where to go.
Pitfalls
git branch feature maincreates a branch from the current state of main only. If main advances later, feature does not follow automatically. You needmergeorrebase.- You cannot delete the branch you are currently on. Switch somewhere
else (
git switch main) first. git branch -D featuresilently deletes the branch even if it has unmerged commits. If you did this by accident,git reflogshows the SHA so you can recreate the branch, but the branch name itself must be re-created manually.