History, Diffs, Refs and the Object Model
Git history is a graph of immutable, content-addressed objects. Knowing how refs, revision syntax and range notation walk that graph lets you answer "what changed, where and when" precisely.
Key points
- 1
Objects: blobs hold content, trees map names to blobs and subtrees, commits point to one tree plus parents; IDs are hashes, so identical content is stored once.
- 2
Branches are refs holding one commit ID; HEAD is usually a symbolic ref to a branch and becomes "detached" when it holds a commit ID directly.
- 3
~nwalks first parents;^npicks the n-th parent of a merge;ref@{n}reads the reflog;@{u}is the upstream and@{-1}the previous branch. - 4
In log,
A..Bis "in B, not in A" andA...Bis the symmetric difference. In diff,A..BequalsA BandA...Bdiffs from the merge base to B. - 5
git diffis working tree vs index,--stagedis index vs HEAD, andgit diff HEADis working tree vs HEAD. - 6
-Sfinds commits that change how often a string occurs;-Gfinds patches with matching lines;-Ltraces a line range or function;--followtracks one file across renames. - 7
--first-parentshows the mainline with one merge per feature;--sincefilters on committer date, which rebases reset.
Common traps
git diff main..featureis not what a pull request shows; usemain...feature.HEAD~2andHEAD^2are different commits whenever merges are involved.Commits made on a detached HEAD are not deleted when you switch away, but they become unreachable and expire with the reflog.
Read the source
Test yourself on History, Diffs, Refs and the Object Model
Ten questions, with the answer and explanation after each one.