What a branch really is
Intermediate Core Git Git CLI
Why this matters
People imagine a branch as a copy of the project, and then everything about branches feels heavy: copying takes time, switching means moving folders, deleting throws work away. None of that is true. A branch is a 41-byte file containing a hash. Once you see it that way, every branch operation becomes cheap and predictable.
A label on a commit
The commits themselves belong to no branch. A commit is "on" a branch if you can reach it by starting at the branch's pointer and following parents backwards. That is why one commit can be on several branches at once, and why merging is about moving pointers.
Watch it in the playground's history. Right after creating a branch, both labels sit on the same commit:
$ git switch -c docs/12-windows-install-stepsSwitched to a new branch 'docs/12-windows-install-steps'$ git log --oneline --graph --all --decorate* 8fa922e (HEAD -> docs/12-windows-install-steps, tag: v1.2.0, origin/main, main) Initial import of trailguideAfter one commit on the branch, only its label moved:
$ git log --oneline --graph --all --decorate* 510f1e0 (HEAD -> docs/12-windows-install-steps) docs: add Windows steps to installation guide (#12)
* 8fa922e (tag: v1.2.0, origin/main, main) Initial import of trailguidemain still points at 8fa922e. HEAD -> docs/12-… says which branch you are on, and therefore which label will move with your next commit.
Listing branches
$ git branch* docs/12-windows-install-steps
mainThe * marks the current branch. git branch -a adds the remote-tracking branches (remotes/origin/main); git branch -vv shows each branch's commit and which remote branch it tracks:
$ git branch -vv* docs/12-windows-install-steps 510f1e0 [origin/docs/12-windows-install-steps] docs: add Windows steps to installation guide (#12)
main 8fa922e [origin/main] Initial import of trailguideSwitching changes your files
Switching branches makes the working tree match the branch's commit: files that differ are rewritten, files that exist only on the other branch appear or disappear. That is not deletion; it is Git showing you a different snapshot. Your uncommitted edits, however, come along only if they do not conflict with the switch — otherwise Git refuses (lesson 5.7).
$ git switch mainSwitched to branch 'main'
Your branch is up to date with 'origin/main'.The Windows section of the installation guide is gone from disk now, and will be back the moment you switch to docs/12-… again.
Why this makes branches safe
- Creating a branch is instant and changes nothing.
- Committing on a branch cannot affect
mainor any other branch; only your label moves. - Deleting a branch removes a label. The commits stay until nothing points at them, and even then remain recoverable for a while (lesson 12.5). Git refuses to delete a branch whose commits are not merged anywhere unless you force it.
- Switching rewrites files to a known snapshot; nothing committed is ever lost by switching.
Common mistakes
- Thinking "the file was deleted" after a switch. It exists on the other branch. Switch back or
git log --all -- <file>. - Committing on the wrong branch because the label you thought you were on was not
HEAD ->. Read thegit statusfirst line (lesson 12.7 fixes it). - Expecting a branch to "contain" its history separately. Branches share commits;
git log main..docs/12shows only the commits the branch adds (lesson 6.5).
Try it yourself
Goal: watch a label move.
- In the playground, run
git log --oneline --graph --all --decorate -3and note wheremainis. - Create a branch:
git switch -c docs/practice-branch, then run the same log: both labels on one commit. - Make an empty commit:
git commit --allow-empty -m "docs: practice"; run the log again. - Run
cat .git/refs/heads/mainandcat .git/refs/heads/docs/practice-branch.
Expected result: after step 3 the branch label is one commit ahead of main; the two files in step 4 contain different hashes, the second matching the newest commit.
Show solution
The branch files are the labels. main's file still holds the older hash because no commit was made on main. Switch back with git switch main and delete the practice branch with git branch -D docs/practice-branch (capital D because its commit is not merged).