Advanced Revision Selection, Log Search, Path History, and Ancestry Analysis: Concepts, Architecture, and Mental Model
Build a precise mental model of Git revision names, parent/reflog selectors, reachability set algebra, two-dot/three-dot ranges, path history, first-parent traversal, ancestry paths, and history simplification.
Learning objectives
- Resolve symbolic revision names and derived parent/reflog selectors to exact objects.
- Express commit sets using reachability, exclusions, two-dot, and three-dot notation.
- Distinguish three-dot semantics in revision walking from git diff tree comparisons.
- Explain path-limited history, rename following, first-parent, ancestry-path, and simplification.
- Define operational history reports as explicit, reproducible queries.
1. History questions are set-selection problems
Chapter 14 established an important precondition: before trusting a
history query, know whether your clone actually contains the
required history. Chapter 15 now turns Git's revision language into
a precise query system. Instead of scrolling through
git log and guessing, you will state the exact commit
set, path scope, ancestry relation, or object you need.
Operational questions such as “what reached production?”, “which commits exist only on this branch?”, “what changed after the incident began?”, and “which commit introduced this file before it was renamed?” all require different selectors. A command can be syntactically valid yet answer the wrong question.
2. Resolve names before building complex queries
git status --short --branch
git show-ref --heads --tags
git rev-parse HEAD
git rev-parse --symbolic-full-name HEAD
git rev-parse trunk
git log --graph --decorate --oneline --all --max-count=25
git rev-parse converts revision spelling into object
names or symbolic names. It is a useful preflight because you can
prove what trunk, HEAD, or a tag means
before using it in a larger expression.
3. A revision name is a way to identify an object or starting point
Git accepts full object IDs, unique prefixes, branch names, tags,
remote-tracking refs, symbolic refs such as HEAD, and
several derived forms. Do not hard-code assumptions about a fixed
40-character SHA-1 form: repositories can use other object formats,
and abbreviated IDs are valid only when unique in the current
repository.
git rev-parse HEAD
git rev-parse HEAD^{commit}
git rev-parse refs/heads/trunk
4. Parent and ancestor selectors navigate the commit graph
For a commit C, C^ means its first parent;
C^2 means its second parent when C is a
merge; and C~3 means follow the first-parent chain
three generations. The distinction matters at merges.
flowchart LR A[A] --> B[B] B --> T[T: trunk work] B --> F1[F1: feature] F1 --> F2[F2] T --> M[M: merge] F2 --> M M --> R[R: release] P1[M^1 = T] --> T P2[M^2 = F2] --> F2 FP[M~2 follows first parents] --> B
The merge M has two direct parents.
M^1 follows the branch that was checked out when the
merge was created; M^2 follows the merged side.
~ repeatedly follows only first parents, so it is
useful for deployment/mainline questions but not for enumerating
every side branch.
5. Reflog-style selectors name prior local ref states
Selectors such as trunk@{1} mean the previous recorded
value of that local ref, while @{-1} names the branch
or commit checked out immediately before the current one.
@{u} resolves a configured upstream. These selectors
depend on local reflog/config state and therefore are not portable
release identifiers.
git reflog --date=iso --max-count=10
git rev-parse 'trunk@{1}'
git rev-parse '@{-1}'
git rev-parse --symbolic-full-name '@{u}'
Quote brace-containing revision expressions in shell examples when doing so avoids shell interpretation. A selector can be valid in one clone and unavailable in another because reflogs are local.
6. Revision walking is set algebra over reachability
For commands such as git log and
git rev-list, naming a commit includes commits
reachable from it by parent links. Prefixing a revision with
^ excludes commits reachable from that revision.
git rev-list trunk ^release-base
git log --oneline trunk ^release-base
Read the expression as: “commits reachable from trunk,
minus commits already reachable from release-base.”
This is the foundation for release ranges and branch-unique queries.
7. Two-dot means reachable from the right, excluding the left
For revision-walking commands, A..B is shorthand for
B ^A. It asks what B can reach that
A cannot.
git log --oneline trunk..feature/metrics
git rev-list --count trunk..feature/metrics
This is a precise version of “what commits are unique to the feature relative to trunk?”
8. Three-dot in revision walking means symmetric difference
For git log/git rev-list,
A...B means commits reachable from either side but not
reachable from both. Adding --left-right marks which
side each selected commit came from.
git log --left-right --graph --oneline A...B
git rev-list --left-right --count A...B
This is useful for divergence analysis because it shows unique work on both sides while excluding shared ancestry.
9. The same A...B spelling means something different to
git diff
git diff A...B compares the tree at a merge base of
A and B with the tree at B.
It is a two-tree comparison, not a printed symmetric-difference
commit set.
BASE=$(git merge-base A B)
git diff "$BASE" B
git diff A...B
The two diff commands are equivalent in the common single-best-merge-base case. The operational lesson is to define your question first: “which commits?” and “which file changes?” are not the same query.
10. A path after -- filters history to changes relevant
to that path
git log --oneline -- services/api/settings.txt
git log -p -- services/api/settings.txt
The separator -- disambiguates revisions from paths.
Path-limited history also activates history simplification rules, so
a compact path log may omit commits/merge sides that do not
contribute to the selected path's final explanation.
11. --follow can trace one file beyond a rename—with
limits
git log --follow --oneline -- services/api/settings.txt
Current Git documents --follow for a single file.
Rename detection is heuristic, and following across complex
non-linear history or arbitrary directory transformations is not a
universal lineage oracle. For audits, corroborate with explicit
commits/diffs when history is complicated.
12. First-parent history answers “how did this integration line evolve?”
git log --first-parent --graph --oneline trunk
At each merge, --first-parent follows only the first
parent. This suppresses the individual commits brought in from
merged branches and emphasizes the sequence of commits and merge
events on the chosen line. Deployment/release timelines often
benefit from this view.
13. --ancestry-path narrows a range to commits on the
descendant chain
Given D..M, normal range semantics can include commits
that M reaches but that are not descendants of
D. Adding --ancestry-path retains commits
that lie on ancestry paths between the endpoints.
git log --ancestry-path --oneline incident-start..trunk
This is useful for questions such as “which later commits could contain the effect introduced at this known commit?”
14. History views are queries, not literal dumps of every graph node
With path filtering, Git classifies commits relative to whether
their selected-path trees are the same as their parents. Default
history simplification can prune side history.
--full-history follows more parent history;
--simplify-merges can then remove merges that add no
selected-path contribution while retaining meaningful topology.
git log --oneline -- path/to/file
git log --full-history --oneline -- path/to/file
git log --full-history --simplify-merges --oneline -- path/to/file
These are different questions. If an incident depends on whether a side branch touched a file, do not assume the shortest default path log is complete evidence.
15. DevOps connection — operational reports should state their commit-set definition
A release report should say whether it means
v2.3.0..v2.4.0, first-parent commits, all reachable
commits, or a path-limited subset. An incident timeline should name
the start point and ancestry rule. A deployment provenance report
should resolve symbolic refs to exact object IDs. Reproducible
history analysis means storing the query, endpoints, and resulting
IDs—not a screenshot of a log.
16. Knowledge check
Question 1. What does A..B mean to
git log?
B ^A.
Question 2. What does A...B mean to
git log?
Question 3. Does git diff A...B print the
symmetric-difference commit set?
Question 4. Why is trunk@{1} not a portable
deployment identifier?
Question 5. What does
--first-parent emphasize?
17. Summary
Revision syntax is a query language over refs, object IDs, parents, reflogs, reachability, and paths. Two-dot, three-dot, parent selectors, first-parent walks, ancestry paths, and path simplification answer distinct questions. Resolve endpoints and define the intended set before choosing display options.
Authoritative references
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.