Exploring History with git log
Module 01 45 min
Section Objectives
- Browse commit history with different formats
- Filter history by author, date, file, or message
- Visualize branches graphically
- Search through the history for specific changes
Basic git log
git log
Output:
commit d5a1b4c2e3f4a5b6c7d8e9f0a1b2c3 (HEAD -> main)
Author: Alice Dupont <alice@example.com>
Date: Wed Mar 18 14:30:00 2026 +0000
feat(auth): add user login endpoint
commit c2e8f3a1b2c3d4e5f6a7b8c9d0e1f2 (origin/main)
Author: Alice Dupont <alice@example.com>
Date: Tue Mar 17 10:15:00 2026 +0000
fix(utils): correct email normalization
Essential git log Formats
# Compact: one line per commit
git log --oneline
# With branch/tag graph
git log --oneline --graph
# Full graph with all branches
git log --oneline --graph --decorate --all
# Detailed: stats (files changed, insertions, deletions)
git log --stat
# Detailed: full diff of each commit
git log -p # or --patch
# Show only N last commits
git log -5
git log -10 --oneline
Sample Output of --oneline --graph --all
* d5a1b4c (HEAD -> main) feat: add dashboard
* c2e8f3a fix: correct email validation
| * b7c9d1e (feature/login) feat: login form UI
| * a3f4b2c feat: start login feature
|/
* e1f2a3b Initial commit
Filtering History
By Author
# Commits by a specific author
git log --author="Alice"
git log --author="alice@example.com"
By Date
# Since a specific date
git log --since="2026-01-01"
git log --after="2 weeks ago"
git log --after="yesterday"
# Before a specific date
git log --until="2026-03-01"
git log --before="1 month ago"
# Between two dates
git log --after="2026-01-01" --before="2026-03-01"
By Commit Message
# Search for a keyword in messages
git log --grep="fix"
git log --grep="feat(auth)"
# Case insensitive search
git log --grep="login" -i
By File
# Only commits that touched a specific file
git log -- README.md
git log -- src/auth/login.py
# Only commits that touched a folder
git log -- src/
# Commits that touched a file, even after it was renamed
git log --follow -- src/auth/login.py
By Content (Pickaxe)
# Commits that ADDED or REMOVED a specific string
git log -S "password" # Added/removed the word "password"
git log -S "def login" # Added/removed the login function
# Commits where content CHANGED (regex)
git log -G "password.*hash"
Formatting Output
Custom Format
# Custom format
git log --format="%h %an %ar %s"
# %h = short hash
# %H = full hash
# %an = author name
# %ae = author email
# %ar = relative date ("3 days ago")
# %ad = absolute date
# %s = commit subject (first line)
# %b = body
# %d = refs (branches, tags)
# Example output:
# d5a1b4c Alice Dupont 2 days ago feat: add dashboard
Useful Formats
# Compact with relative date
git log --format="%C(yellow)%h%C(reset) %C(blue)%ar%C(reset) %s %C(green)(%an)%C(reset)"
# Export to file for documentation
git log --format="%h|%an|%ar|%s" > commit-history.csv
Navigating the History
git show — Details of a Commit
# Show details of last commit
git show
# Show a specific commit
git show d5a1b4c
git show HEAD # Last commit
git show HEAD~1 # Second-to-last commit
git show HEAD~3 # 4th-to-last commit
# Show a specific file in a commit
git show d5a1b4c:src/main.py
# Show only changed files (no diff)
git show --stat d5a1b4c
git show --name-only d5a1b4c
Relative References
| Reference | Meaning |
|---|---|
HEAD | Current commit (last on current branch) |
HEAD~1 or HEAD~ | Parent commit (1 before HEAD) |
HEAD~3 | 3 commits before HEAD |
HEAD^ | First parent of HEAD (same as HEAD~1) |
HEAD^2 | Second parent of HEAD (for merges) |
main~5 | 5 commits before the tip of main |
abc1234 | A specific commit by hash |
v1.0 | A tag |
git blame — Who Changed What?
# Show who last modified each line of a file
git blame README.md
# Ignore whitespace changes
git blame -w README.md
# Show only specific lines
git blame -L 10,20 src/main.py
# Show at a specific commit
git blame d5a1b4c -- src/main.py
Output:
d5a1b4c (Alice 2026-03-18 14:30 +0000 1) # My Project
c2e8f3a (Bob 2026-03-10 09:15 +0000 2)
c2e8f3a (Bob 2026-03-10 09:15 +0000 3) ## Installation
a3f4b2c (Alice 2026-03-01 08:00 +0000 4)
a3f4b2c (Alice 2026-03-01 08:00 +0000 5) ```bash
git blame is not for blaming people!
Despite its name, git blame is a collaboration tool, not for blaming colleagues. Use it to understand why code was written a certain way, who to ask for context, and to locate the commit that introduced a change.
Searching History
git log -S — Find a Change
# When was a function added?
git log -S "def authenticate" --oneline
# When was a variable renamed?
git log -S "user_id" --oneline -- src/
# View the exact change
git log -p -S "def authenticate" --oneline
git bisect — Binary Search for a Bug
# Start bisect
git bisect start
# Mark current commit as bad (bug present)
git bisect bad
# Mark an old commit as good (bug not present)
git bisect good v1.0
# Git checks out the middle commit — test it
# If the bug is present:
git bisect bad
# If the bug is absent:
git bisect good
# Git continues narrowing down until finding the exact commit
# At the end:
git bisect reset
Practical Aliases for Log
Add these to your ~/.gitconfig:
git config --global alias.lg "log --oneline --graph --decorate --all"
git config --global alias.ll "log --oneline -15"
git config --global alias.lp "log -p -1"
git config --global alias.ls "log --stat -5"
git config --global alias.lf "log --format='%C(yellow)%h%C(reset) %C(blue)%ar%C(reset) %s %C(green)(%an)%C(reset)'"
Summary Table
| Command | Description |
|---|---|
git log | Full history |
git log --oneline | Compact history |
git log --graph --all | Visual graph of all branches |
git log --stat | History with stats |
git log -p | History with diffs |
git log --author="X" | Filter by author |
git log --since="date" | Filter by date |
git log --grep="text" | Filter by message |
git log -S "code" | Search by content |
git log -- file | Commits affecting a file |
git show <commit> | Details of a commit |
git blame <file> | Who modified each line |