Chapter 15Lesson 01~100 minutes

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.

Revision syntaxCommit setsPath historyAncestry

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.

Parent selectors at a merge
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

Do not transfer range semantics mechanically between commands.

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?

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.

Next

Build a branched history and answer operational questions with exact queries

Lesson 2 creates merges and a rename, then uses rev-parse, rev-list, log, show, path history, first-parent, and ancestry-path to prove each answer.

Authoritative references

 gitrevisions
 git-rev-parse
 git-rev-list
 git-log
 git-diff

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.