History, diff, and blame

Introduction

Once you have commits, Git becomes a time machine: browse history, compare versions, and see who last changed each line. This chapter covers git log, git show, git diff, and git blame—the commands you use daily during code review and debugging.

Prerequisites

git log Variations

Full log:

bash
git log

One line per commit:

bash
git log --oneline

With branch graph:

bash
git log --oneline --graph --decorate --all

Code explanation:

  • --graph — ASCII branch/merge lines
  • --decorate — shows branch and tag names
  • --all — every branch, not only current

Limit count:

bash
git log -3
git log --since="2 weeks ago"

Filter by author or message:

bash
git log --author="Ada"
git log --grep="login"

git show One Commit

Latest commit:

bash
git show

Specific commit:

bash
git show a1b2c3d

Code explanation:

  • Shows metadata, message, and patch (line-by-line diff for that commit)

Name-only or stats:

bash
git show --stat a1b2c3d
git show --name-only a1b2c3d

git diff: Three Comparisons

Working tree vs staging area

What you would commit if you ran git add now on unstaged edits:

bash
git diff

Staging area vs last commit

What your next git commit will include:

bash
git diff --staged

Alias used by many: git diff --cached (same meaning).

Working tree vs last commit

Everything changed since HEAD (staged + unstaged):

bash
git diff HEAD

Compare two commits

bash
git diff a1b2c3d..e4f5g6h
git diff main..feature/login

Code explanation:

  • A..B — changes from A’s tip to B’s tip
  • Useful for PR review before merge

Reading diff Output

diff
diff --git a/src/index.js b/src/index.js
--- a/src/index.js
+++ b/src/index.js
@@ -1 +1 @@
-console.log('hello');
+console.log('hello git');
PrefixMeaning
- red lineRemoved
+ green lineAdded
@@**Line number context

git blame Line History

Who last touched each line of a file:

bash
git blame src/index.js

Specific lines:

bash
git blame -L 10,20 README.md

Code explanation:

  • Each line shows commit hash, author, date, and content
  • Use when debugging “when did this bug get introduced?”

Ignore whitespace-only changes:

bash
git blame -w src/index.js

Tip

Blame Is Not Shame

blame finds context for fixes—it does not assign fault in code review.

Useful Combinations

bash
# What changed in last commit?
git show HEAD
 
# Files changed between releases
git diff v1.0.0..v1.1.0 --stat
 
# Find commit that added a string (pickaxe)
git log -S "console.log" --oneline

-S searches history for commits that add or remove a string—powerful for archaeology.

Workflow Example

bash
git status
git diff
git add src/index.js
git diff --staged
git commit -m "Refactor index entry point"
git log --oneline -5

Review diffs before commit to catch debug prints and secrets.

FAQ

log opens pager and I am stuck?

Press q to quit. Or git --no-pager log --oneline.

diff shows nothing?

No differences in that comparison—or file is untracked (git diff does not show untracked until add).

blame shows wrong person?

They made the last edit to that line; earlier authors lost in blame until you dig with log -L.

Compare to remote branch?

git diff origin/main..HEAD after git fetch.

Pretty log format?

git log --pretty=format:"%h %s" — customize columns.

GUI alternatives?

gitk, VS Code Source Control timeline, GitHub compare view—same data.