Branching
Why Branching Matters
Section titled “Why Branching Matters”Branching is the mechanism that enables parallel development — multiple developers (or a single developer working on multiple features) can modify the codebase independently, then integrate their changes. Git”s branching model is one of its defining strengths: branches are cheap ( creation), fast to switch, and designed to be created and deleted frequently.
This contrasts sharply with older VCS where branching was an expensive operation that involved copying the entire directory tree (CVS) or was mediated by a central server (early SVN).
Branch Internals
Section titled “Branch Internals”A branch in Git is nothing more than a 40-byte text file containing a SHA-1 hash. Creating a branch does not copy any files or objects — it writes a single reference:
$ git branch feature-auth## Equivalent to: echo $(git rev-parse HEAD) > .git/refs/heads/feature-authThis means:
- Creating 1,000 branches costs the same as creating 1 (a few microseconds).
- Deleting a branch does not delete any commits — it only removes the reference.
- A commit can be reachable from multiple branches simultaneously.
gitGraph
commit id: "A"
commit id: "B"
commit id: "C"
branch feature
checkout feature
commit id: "D"
commit id: "E"
checkout main
commit id: "F"In the graph above:
mainpoints to commitF.featurepoints to commitE.- Commits
A``B``Care shared by both branches — no duplication. - Commit
DandEare only reachable fromfeature. - Commit
Fis only reachable frommain.
Creating and Managing Branches
Section titled “Creating and Managing Branches”Creating Branches
Section titled “Creating Branches”## Create a branch from HEAD (does not switch to it)$ git branch feature-auth
# Create and switch in one step$ git switch -c feature-auth
# Create a branch from a specific commit$ git branch release-1.0 a3f2b1c
# Create a branch from a remote-tracking branch$ git switch -c feature-auth origin/feature-authListing and Inspecting Branches
Section titled “Listing and Inspecting Branches”# List local branches$ git branch
# List all branches (local + remote-tracking)$ git branch -a
# List branches with their last commit$ git branch -v
# Show which branches contain a specific commit$ git branch --contains a3f2b1c
# Show merged branches (branches whose commits are all in HEAD)$ git branch --merged
# Show unmerged branches (branches with commits not in HEAD)$ git branch --no-mergedSwitching Branches
Section titled “Switching Branches”Git provides two commands for switching branches. git switch is the modern command (Git 2.23+); git checkout is the legacy command that serves double duty (switch branches and restore files).
# Modern (recommended)$ git switch main
# Legacy (still widely used)$ git checkout mainWhat Happens During a Branch Switch
Section titled “What Happens During a Branch Switch”When you run git switch mainGit performs the following:
- Validate: Check that the working directory is clean (or that changes can be carried over).
- Update HEAD: Write
ref: refs/heads/mainto.git/HEAD. - Update the index: Load the tree object pointed to by
maininto the index. - Update the working directory: Compare the new index with the current working directory, and add, modify, or delete files as needed.
flowchart LR
A["git switch main"] --> B{"Working directory<br/>is clean?"}
B -->|Yes| C["Update HEAD"]
C --> D["Update index"]
D --> E["Update working directory"]
B -->|No| F{"Changes conflict<br/>with target branch?"}
F -->|No| G["Carry changes over<br/>(update index only)"]
G --> C
F -->|Yes| H["Error: would overwrite<br/>local changes"]
H --> I["Commit, stash,<br/>or discard changes first"]If you have uncommitted changes that do not conflict with the target branch, Git carries them over. If they do conflict, Git refuses to switch:
error: Your local changes to the following files would be overwritten by checkout: src/main.cPlease commit your changes or stash them before you switch branches.AbortingForce Switching
Section titled “Force Switching”If you want to discard local changes and switch anyway:
$ git switch -f main# Discards all uncommitted changes in the working directory and indexIntuition
Section titled “Intuition”Branching in Git is like creating a parallel universe: you can experiment freely without affecting the main line. A branch is just a pointer to a commit, so creating one is instant. When you switch branches, Git updates your working directory to match the snapshot at that commit. Think of it as time travel: you jump to a different point in the codebase’s history and work from there. Merging brings the parallel universes back together.