Reading history — log, show, blame, and diff between commits
A project's history is only useful if it's actually readable later. These four commands are how you go from "something's wrong" to "here's the exact commit and line that caused it," instead of guessing.
3 min read
git log: browsing the commit history, with real filters
git log --oneline -5 -- last 5 commits, one line each
git log --author="Ada" -- only commits by a specific author
git log --since="2 weeks ago" -- only recent commits
git log -- app.py -- only commits that touched this specific file
The daily-workflow lesson covered git log --oneline as the basic view — git log also accepts real filters, not just formatting flags: by author, by date range, or restricted to commits that touched one specific file (-- filename, with the -- distinguishing "this is a file path" from "this is another flag"). This turns git log from "scroll through everything" into "show me exactly the slice of history relevant to what I'm actually trying to understand."
git show: the full detail of one specific commit
git show a3f8e21
commit a3f8e21...
Author: Ada Lovelace <ada@example.com>
Date: Mon Jan 15 10:30:00 2024
Fix greeting to use an f-string
diff --git a/app.py b/app.py
- def greet(name):
- return "Hello " + name
+ def greet(name):
+ return f"Hello {name}"
git show, given a commit hash, displays everything about that one specific commit — its full message, author, date, and the actual diff of what changed in that commit specifically. This is the natural next step after spotting an interesting commit in git log --oneline's condensed view — log finds the commit, show reveals exactly what it did.
git diff: comparing two arbitrary points, not just uncommitted changes
git diff HEAD~3 HEAD -- changes between 3 commits ago and now
git diff main feature-login -- changes between two branches
git diff a3f8e21 9c2d104 -- changes between two specific commits
The daily-workflow lesson covered git diff for uncommitted changes — the same command also compares any two commits, or any two branches, directly against each other. HEAD refers to the current commit; HEAD~3 means "three commits before the current one" — this relative notation is genuinely useful for "what's changed in the last few commits" without needing to look up specific commit hashes first.
git blame: who last changed each line, and in which commit
$ git blame app.py
a3f8e21 (Ada Lovelace 2024-01-15) def greet(name):
9c2d104 (Grace Hopper 2024-01-10) return f"Hello {name}"
git blame, given a filename, shows line by line which commit last modified each line and who authored it — despite the name, this is a genuinely neutral tool for tracing history, not literally about assigning fault. It's the practical way to answer "why is this line written this way" or "who do I ask about this specific piece of logic" — following the commit hash it reports back into git show reveals the full context and reasoning behind that specific change.
Putting all four together: an actual debugging workflow
1. Bug appears in production. Which lines does it involve?
2. git blame the file -> find which commit last touched those lines
3. git show <that commit> -> read the full change and its message
4. git log -- <the file> -> see the file's broader change history, for more context
5. git diff between two versions -> confirm exactly what's different if needed
This is the real, practical value of a readable history: instead of guessing why a bug exists, these four commands turn "something's wrong here" into "this specific commit, by this person, for this stated reason, is what changed this line" — which is exactly why the daily-workflow lesson's advice (write real commit messages, commit small and often) pays off later specifically through this kind of investigation, months after anyone remembers writing the code.
Further reading
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What does git log -- app.py show, compared to plain git log?
2. How does git show relate to git log --oneline in a typical investigation?
3. Besides uncommitted changes, what else can git diff compare?
4. What does git blame actually show, and what is it genuinely used for?