Git Branch
Treat a branch as a movable pointer, follow HEAD, and recover from detached HEAD without discarding wanted commits.
Branches are names in a graph
A branch is a movable ref
A local branch such as main stores the object ID of one commit. That commit reaches its parents, so one pointer gives Git access to an entire line of history. Creating a branch adds another name at a chosen commit; it does not duplicate commit objects or working files.
mainC3Document formatter usage
feature/searchC2Add catalog data
SHARED PARENTC1Initialize application
Both branch names can point to the same commit. Once one branch receives a new commit, its ref advances and the names diverge. The shared ancestors remain one set of objects.
HEAD identifies your checkout context
In the normal attached state, HEAD is a symbolic reference to the current local branch. The branch points to a commit. Git uses that chain to know which ref should advance after the next commit.
git status --short --branch
git branch --show-current
git log --oneline --decorate --graph --all
git rev-parse HEAD
git symbolic-ref --short HEADHEAD → refs/heads/main → C3
A new commit creates C4 with C3 as parent, then moves main to C4.
HEAD → C3
A new commit can still be created, but no local branch automatically moves to name it.
git symbolic-ref --short HEAD prints the current branch in attached state and exits nonzero when HEAD is detached. git branch --show-current prints the branch name or an empty result when detached.
Test what you learned
Type the command that prints only the currently attached branch name.
A commit advances only the attached branch
- 01Read HEAD
Git resolves HEAD to the current branch and its tip commit.
- 02Create the commit object
The new commit records the staged tree, metadata, message, and current tip as parent.
- 03Move the branch ref
The attached branch changes from the former tip to the new commit.
- 04Keep other refs still
Unrelated branches remain at their existing commits until an explicit operation moves them.
This is why switching branches before committing matters: the same staged snapshot committed on another attached branch advances a different name and changes the story told by the graph.
Create and switch branches explicitly
# Create a branch at the current commit and switch to it
git switch -c feature/search
# Make and inspect a commit on that branch
git add src/search.js
git diff --cached
git commit -m "Add catalog search"
# Return to main without merging
git switch main
git log --oneline --decorate --graph --allgit branch NAME
Create NAME at the current commit without switching the worktree or HEAD.
git switch NAME
Attach HEAD to an existing local branch and update the working tree and index for its commit.
git switch -c NAME
Create NAME at the chosen/default start point and switch to it.
git switch -C NAME START
Create or forcibly reset NAME to START before switching. This can discard a branch tip and needs preservation evidence.
Older Git often used git checkout both to switch branches and to restore files. This course uses git switch for branch movement. Restoring working-tree files belongs with Git Reset, where git restore is the dedicated command. git checkout still exists; treat it as an older combined Git interface, not a GitHub feature.
Switch only when the working state can survive
Git may carry compatible uncommitted changes across a switch, or refuse when checkout would overwrite them. A successful switch with local edits does not mean those edits belong to the destination branch.
git status --short
git diff
git diff --cached
git branch --show-current
# Then choose deliberately:
# - commit a coherent checkpoint
# - create a named stash for a brief pause
# - use a linked worktree for parallel contexts
# - restore only confirmed disposable editsDo not force a switch to escape a confusing state. First identify every staged, unstaged, untracked, and ignored path and choose its destination.
Create a branch from the right start point
git switch -c feature/search main
git switch -c hotfix/payment v2.4.1
git branch investigation 8f42d91
git show --no-patch --decorate feature/search
git merge-base main feature/searchA branch can start at any resolvable commit, tag, or ref. Name the start point when it matters; “current commit” is safe only when you have proved where HEAD is. git merge-base identifies a best common ancestor used by later integration reasoning.
Read branch divergence without switching
git log --oneline --decorate --graph --all
git log main..feature/search --oneline
git log feature/search..main --oneline
git diff main...feature/search
git branch --contains 8f42d91
git branch --merged main
git branch --no-merged mainmain..feature
Commits reachable from feature that are not reachable from main.
feature..main
Commits reachable from main that are not reachable from feature.
diff main...feature
Patch from their merge base to feature—the feature-side change since divergence.
branch --contains
Local branches whose histories reach the named commit.
Rename and delete refs safely
# Rename the current branch
git branch -m feature/catalog-search
# Delete only when Git considers it merged
git branch -d feature/catalog-search
# Inspect before considering force deletion
git log main..feature/catalog-search --oneline
git branch --contains feature/catalog-searchRenaming changes the local ref name, not the commit objects. Lowercase -d performs a merged-history safety check. Uppercase -D bypasses that protection; use it only after preserving or deliberately abandoning every commit unique to the branch.
Detached HEAD is a valid inspection state
Checking out a commit, remote-tracking ref, or tag can detach HEAD. This is useful for inspecting or testing an exact snapshot without moving a branch.
git switch --detach 8f42d91
git branch --show-current
git rev-parse --short HEAD
git status --short --branch
# Inspect or test, then return without creating commits:
git switch mainDetached does not mean corrupted. The warning matters only when you create wanted commits and then switch away without giving them a durable ref.
Commits can exist while HEAD is detached
Git can create a commit with detached HEAD as its parent. HEAD advances directly to the new commit, but no local branch name follows. The commit is real and visible in the current checkout; it becomes harder to find after you leave.
mainC3Main remains here.
DETACHC2HEAD was detached at an older commit.
HEADD1Wanted experiment commit has no branch name yet.
Rescue detached work immediately
# While detached, preserve the current commit with a new branch
git switch -c rescue/detached-work
# Verify HEAD is attached and the commit is reachable by name
git branch --show-current
git log --oneline --decorate --graph --allIf you already switched away, inspect the reflog, verify the candidate commit with git show, and create a branch at the exact ID:
git reflog --date=iso
git show --stat <detached-commit>
git branch rescue/detached-work <detached-commit>
git log --oneline --decorate --graph --allTest what you learned
While still on a wanted detached commit, type the command that creates and switches to rescue/experiment.
Understand the unborn initial branch
Immediately after git init -b main, HEAD can symbolically reference main even though no commit exists and the branch ref has not been created. This is an unborn branch state.
git symbolic-ref --short HEAD
# main
git rev-parse --verify HEAD
# exits nonzero because no commit exists yet
# The first commit creates the commit and makes main point to it.This explains why some revision commands fail before the first commit while the status message can still name the intended branch.
Guided practice: draw and move refs
Use a disposable repository with three commits on main. Keep the working tree clean before each switch.
- 01Draw the attached state
Record HEAD, main, the tip ID, and three parent relationships.
- 02Create a feature branch
Switch to a new branch, make one coherent commit, and prove only that branch advanced.
- 03Return to main
Show that the feature commit remains in the graph but is not reachable from main.
- 04Detach at the root
Inspect the snapshot, create one experiment commit, and draw HEAD without a branch.
- 05Rescue the experiment
Create a branch before leaving, return to main, and prove all refs and commits remain reachable.
Independent lab: recover an unnamed experiment
Create a disposable five-commit history and two local branches. Then complete this audit:
- Draw the initial graph with exact branch tips and HEAD attachment.
- Create a feature branch from the third commit, add two commits, and compare both directional ranges with main.
- Return to main and detach at the second commit.
- Create two experimental commits while detached and switch back to main without first naming them.
- Use reflog and show to identify the correct detached tip without guessing.
- Create
rescue/experimentat that tip and prove both experiment commits are reachable. - Use merged and no-merged reports to decide which practice branch can be deleted with lowercase
-d. - Finish with clean status and a graph whose every ref and parent edge you can explain.
Common branch and HEAD mistakes
Treating a branch as copied files
The ref points to one commit. Worktree checkout produces files from the selected snapshot.
Creating from the wrong tip
Prove HEAD or name the intended start revision explicitly before creating a branch.
Assuming switch merges work
Switch changes checkout context; branch histories remain distinct until integration.
Carrying edits unknowingly
Inspect status and both diffs before and after switching so local changes retain an intentional owner.
Panicking at detached HEAD
Inspection is safe. Wanted commits need a branch name before their reflog-only path expires.
Force-deleting without containment proof
-D bypasses a useful guard. Preserve or explicitly abandon unique commits first.
Lesson review
You can now reason about branches as movable names over a shared commit graph. HEAD determines the current checkout and, when attached, which branch advances. Detached HEAD is useful and recoverable as long as wanted commits receive a durable ref.
- I distinguish branch refs, HEAD, commits, the index, and working-tree files.
- I can predict which branch advances after a commit.
- I create branches from verified start points and inspect divergence without switching.
- I recognize detached HEAD and preserve wanted commits with a branch.
- I use containment and merged-history evidence before deleting a branch.