Commits, Diffs, History Inspection, Revision Ranges, and Message Discipline: Diagnostics, Failure Modes, Security, and Performance
Diagnose misleading history and diff views safely: dotted-range mistakes, patch-versus-object confusion, accidental commit scope, revision/path ambiguity, hidden history from filters, and prohibited published-history rewrites.
Learning objectives
- Apply an evidence-first sequence before changing refs or commits.
- Diagnose A..B versus A...B mistakes separately for traversal and diff commands.
- Distinguish computed patch output from stored commit-object content.
- Prevent accidental mixing of staged and unstaged tracked changes, including commit -a behavior.
- Recognize when filters or history simplification hide commits and when published-history policy forbids amend/rewrite.
1. Diagnostic sequence — preserve the graph before changing it
- Preserve evidence: exact command, current branch/OID, status, relevant refs.
- Inspect working tree/index: ordinary and staged diff.
- Inspect graph: unfiltered decorated log/rev-list before adding filters.
- Inspect configuration: aliases, pretty formats, mailmap, diff settings only when output differences point there.
- Identify the layer: object, ref, commit set, snapshot comparison, path filter, or presentation.
- Choose the least destructive correction and verify the question again.
2. Failure mode — reading A..B and
A...B as interchangeable
Suppose two branches diverged. This pair does not answer the same question:
git log --oneline A..B
git log --left-right --oneline A...B
The first selects B-only reachable commits. The second selects commits unique to either side. If a reviewer says “show me everything different between the branches,” first clarify whether they mean unique commits on both sides or snapshot content difference.
3. Intentionally broken expectation — git diff A...B is
not a symmetric patch set
A learner runs:
git diff trunk...feature
and expects it to include both trunk-only and feature-only changes
because git log trunk...feature used symmetric
difference. That expectation is wrong. In git diff, the
three-dot form compares the merge base against B.
Repair the question explicitly:
# Endpoint snapshots
git diff trunk feature
# Feature-side changes since divergence
git diff trunk...feature
# Commit sets unique to both sides
git rev-list --left-right trunk...feature
4. Failure mode — treating formatted patch output as the commit object
git show HEAD
git cat-file -p HEAD
git show --no-patch --format=raw HEAD
The first command normally shows commit metadata/message plus a
computed diff. cat-file -p exposes the commit object's
stored fields. If a diff algorithm or context-line setting changes
the patch view, the commit object does not change.
5. Failure mode — staged and unstaged changes accidentally mixed into one commit
Before committing, always ask which paths/hunks are actually in the index:
git status --short
git diff
git diff --staged
git commit --dry-run
A particularly dangerous convenience is
git commit -a or git commit -am: Git
automatically stages modifications/deletions of already-tracked
files for that commit. It does not add new untracked files, but it
can include tracked working-tree changes you intentionally left
unstaged.
-a only when that behavior is exactly your
intention.
It is not a substitute for reviewing the index.
6. Failure mode — a revision and path share the same name
With a branch named release and a path named
release, a command such as
git log release is naturally interpreted as a revision
traversal.
git log --oneline release
git log --oneline -- release
git diff HEAD -- release
The standalone -- marks the path boundary. If a token
begins with a dash, the boundary also prevents it being treated as
another option after option parsing is complete.
7. Failure mode — history filters hide the commit you are looking for
History output is the result of selection, simplification, ordering, and formatting. These commands can legitimately show different sets:
git log --oneline --since='2 weeks ago'
git log --oneline --grep='timeout'
git log --oneline -- src/service.py
git log --full-history --oneline -- src/service.py
If a known commit “disappears,” remove filters one by one and inspect the full decorated graph. Path-limited history can simplify merges; date/message filters can exclude relevant commits by design.
8. Failure mode — rewriting published history just to improve presentation
git commit --amend creates a replacement commit. Even a
message-only amendment changes the commit object/OID. If the old
commit has already been shared and project policy forbids rewriting
published history, a prettier message is not sufficient
justification.
9. Security concerns specific to history and diff views
- Commit messages are stored in history; do not paste tokens, private URLs, passwords, or secret incident payloads into them.
-
git show/git diffcan expose secrets present in historical file content. Sanitize logs before posting them to support channels. - Changing a message or diff display does not remove secret content from old objects. Rotate/revoke leaked credentials first; history-removal is a separate Chapter 21 procedure.
10. Performance without sacrificing correctness
Limit output intentionally: --no-patch when only
metadata is needed, --max-count for bounded recent
views, --format for machine reports, or path filters
when the question truly concerns one path. But performance filters
also narrow evidence. During incident forensics, preserve an
unfiltered baseline command in the report so another engineer can
reproduce how the narrower result was derived.
11. Red-zone operations
git commit --amend, rebase, destructive reset, force
push, reflog expiry, pruning, or secret-rewrite tools all change
history or recovery options. Diagnose with read-only
log/show/rev-list/diff/status commands first.
12. Symptom → likely misunderstanding
| Symptom | Likely issue | First evidence |
|---|---|---|
| Three-dot log has commits from both sides | Symmetric set semantics | rev-list --left-right A...B |
| Three-dot diff shows only feature-side change | Diff merge-base semantics | merge-base + endpoint diffs |
| Commit “contains a patch” that changed after config | Patch is computed presentation | cat-file -p COMMIT |
| Unexpected tracked changes committed | -a or broad staging |
status + staged diff + reflog/log |
| Path history misses known commit | Filter/history simplification | unfiltered graph + --full-history |
13. Knowledge check
Question 1. A reviewer asks for “commits unique to either branch.” Which family of command answers that?
git log A...B or
git rev-list --left-right A...B, because this is a
commit-set question.
Question 2. Why can a diff look different after changing
diff.algorithm even though the commit OIDs are
unchanged?
Question 3. What hidden behavior makes
git commit -am "msg" risky when you intentionally
left a tracked file unstaged?
-a option stages modified/deleted tracked files
for the commit, so that tracked edit can be included despite not
being explicitly added.
Question 4. A path-limited log misses a merge-related commit. What should you do before assuming history is lost?
--full-history -- path or other
history-simplification modes. Filters can legitimately
hide/simplify commits.
Question 5. Why can a message-only amend be unsafe on a shared branch?
14. Summary
History diagnostics start by separating commit sets, snapshot comparisons, object content, filters, and presentation. Most confusing log/diff output can be explained without changing a single ref; preserving that discipline prevents cosmetic problems from becoming history-rewrite incidents.
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.