|$ curl https://forge-ai.dev/api/markdown?path=docs/git/history
$cat docs/git-—-history-&-inspection.md
updated Recently·14 min read·published

Git — History & Inspection

GitIntermediate
Introduction

Git stores a complete, immutable history of every change ever made to your project. The ability to inspect, search, and analyze that history is one of Git's greatest strengths. Whether you are tracking down a bug, auditing changes, or recovering lost work, Git's inspection tools are indispensable.

This guide covers git log formatting and filtering, git blame for finding change origins, git bisect for regression hunting, and git reflog for recovery.

git log Formatting

The git log command is the primary tool for viewing commit history. It offers extensive formatting options to display exactly the information you need.

terminal
Bash
1# Standard log with full details
2git log
3
4# One commit per line (hash + subject)
5git log --oneline
6
7# Show commit graph with one-line format
8git log --oneline --graph
9# * a1b2c3d Add payment feature
10# * e4f5g6h Merge branch 'feature/login'
11# |\
12# | * i7j8k9l Add login validation
13# * | m0n1o2p Fix header styling
14
15# Custom format with --pretty
16git log --pretty=format:"%h %an %ar: %s"
17# a1b2c3d Alice 2 hours ago: Add payment feature
18# e4f5g6h Bob 3 hours ago: Merge branch
19
20# Common format placeholders:
21# %h - abbreviated commit hash
22# %H - full commit hash
23# %an - author name
24# %ae - author email
25# %ar - author date (relative)
26# %s - subject (first line)
27# %d - ref names (branches, tags)
28# %p - parent hashes
29# %C() - color (e.g., %C(red))
30
31# Colorized custom format
32git log --pretty=format:"%C(yellow)%h%Creset %C(cyan)%an%Creset %C(green)%ar%Creset %s"
33
34# Show with diffs
35git log -p
36
37# Show last N commits
38git log -5
39
40# Show commits since a date
41git log --since="2 weeks ago"
42git log --after="2024-01-01" --before="2024-03-01"

info

Create a Git alias for your favorite log format: git config --global alias.lg "log --oneline --graph --all --decorate". Then just type git lg for a beautiful, compact history view.
Filtering History

Git log supports powerful filtering to find specific commits by author, date, file, content, and more.

terminal
Bash
1# Filter by author
2git log --author="Alice"
3git log --author="Alice|Bob" # multiple authors
4
5# Filter by committer (different from author)
6git log --committer="CI Bot"
7
8# Filter by date
9git log --after="2024-01-01" --before="2024-06-01"
10git log --since="2 weeks ago" --until="yesterday"
11
12# Filter by file path (changes to specific files)
13git log -- src/app.js
14git log -- src/ # all files in a directory
15
16# Filter by commit message
17git log --grep="bugfix"
18git log --grep="Fixes #123" --all-match
19
20# Filter by content (commits that changed text)
21git log -S "function validate" --pickaxe-all
22# -S searches for string additions/removals
23# -G searches with regex
24
25# Filter by branch topology
26git log --all # all branches
27git log main..feature # commits in feature not in main
28git log --branches --not --remotes=origin
29
30# Combine filters
31git log --author="Alice" --since="1 month ago" --grep="payment" -- src/
git blame — Finding Who Changed What

git blame annotates each line of a file with the commit, author, and date of the last modification. This is invaluable for understanding why a line was written and finding the right person to ask about a change.

terminal
Bash
1# Show blame for every line of a file
2git blame src/app.js
3
4# Output:
5# a1b2c3d (Alice 2024-03-01 10:00:00 +0000 1) const app = express();
6# e4f5g6h (Bob 2024-03-02 14:30:00 +0000 2) app.use(logger());
7# a1b2c3d (Alice 2024-03-01 10:00:00 +0000 3) app.use(routes);
8
9# Show email instead of name
10git blame -e src/app.js
11
12# Show blame for specific line range
13git blame -L 10,30 src/app.js
14
15# Show the original commit's diff alongside blame
16git blame -L 10,30 -s src/app.js
17
18# Ignore whitespace changes
19git blame -w src/app.js
20
21# Find the commit that introduced a specific line
22git blame -L 15,15 src/app.js
23
24# Show blame with the commit hash in full
25git blame -l src/app.js
26
27# Detect moved or copied lines from other files
28git blame -C src/app.js # within same file
29git blame -C -C src/app.js # across all files in same commit
30git blame -C -C -C src/app.js # across all commits
🔥

pro tip

Use git blame -w to ignore whitespace-only changes. This is essential when a file has gone through a formatter or linter that changed indentation, as blame would otherwise point to the formatting commit instead of the meaningful change.
git bisect — Binary Search for Bugs

git bisect performs a binary search through your commit history to find the exact commit that introduced a bug. With a history of N commits, bisect can find the culprit in log(N) steps — finding a bug among 1,000 commits takes only 10 steps.

terminal
Bash
1# Start bisect
2git bisect start
3
4# Mark the current commit as bad (contains the bug)
5git bisect bad
6
7# Mark an old commit as good (before the bug appeared)
8git bisect good v1.0.0
9
10# Git checks out a commit halfway between good and bad.
11# Test it and mark:
12git bisect good # if this commit works
13# OR
14git bisect bad # if this commit has the bug
15
16# Repeat until Git identifies the first bad commit:
17# a1b2c3d is the first bad commit
18# commit a1b2c3d...
19# Author: Alice <alice@example.com>
20# Date: Mon Mar 4 10:00:00 2024 +0000
21# Add payment validation
22
23# End bisect when done
24git bisect reset
25
26# Automated bisect with a test script
27git bisect start HEAD v1.0.0
28git bisect run npm test
29# Git automatically runs "npm test" at each step
30# npm test exit code 0 = good, non-zero = bad

best practice

Write a reliable, fast test script for git bisect run. The script should return 0 for good commits and 1-127 for bad commits (exit code 125 means "skip this commit — cannot test"). Automated bisect is especially powerful for performance regressions where manual testing is impractical.
git reflog — Recovery Safety Net

The reflog ("reference log") records every movement of HEAD and branch pointers in your local repository — including commits made, rebases, resets, and merges. It is your safety net for recovering lost work.

terminal
Bash
1# View the reflog
2git reflog
3# a1b2c3d HEAD@{0}: commit: Add payment validation
4# e4f5g6h HEAD@{1}: rebase: Add login form
5# i7j8k9l HEAD@{2}: reset: moving to HEAD~1
6# m0n1o2p HEAD@{3}: commit: Add login form
7# q3r4s5t HEAD@{4}: checkout: moving from main to feature
8
9# Show reflog for a specific branch
10git reflog show feature
11
12# Show reflog with dates
13git reflog --date=iso
14
15# Recover from a bad reset (go back to where you were)
16git reset HEAD@{1}
17
18# Recover a lost commit (e.g., after rebase gone wrong)
19git cherry-pick a1b2c3d # from reflog output
20
21# Create a branch from a reflog entry
22git branch recovery HEAD@{2}
23
24# View reflog for a specific time window
25git reflog --since="1 hour ago"
26
27# Clean up reflog entries older than 30 days
28git reflog expire --expire=30.days --all
29
30# Reflog retention:
31# - Commits reachable from a ref: 90 days
32# - Commits not reachable: 30 days
33# (configurable with gc.reflogExpire and gc.reflogExpireUnreachable)

warning

The reflog is local to your repository. It is never pushed to a remote and is automatically garbage-collected after 30-90 days. If you need to keep a commit permanently, create a branch or tag pointing to it before the reflog entry expires.
git shortlog & Git Stats

git shortlog summarizes commits grouped by author, making it useful for release notes and contribution analysis.

terminal
Bash
1# Summary of commits grouped by author
2git shortlog
3# Alice (5):
4# Add payment validation
5# Fix login redirect
6# Update tests
7# Bob (3):
8# Add user model
9# Fix database migration
10
11# Show number of commits per author
12git shortlog -sn
13# 5 Alice
14# 3 Bob
15# 2 Charlie
16
17# Shortlog for a specific range (release notes)
18git shortlog v1.0.0..v2.0.0
19
20# Show commit count per author with email
21git shortlog -sne
22
23# Count total commits
24git rev-list --count HEAD
25
26# Count commits per author
27git shortlog -sn --all
28git shortlog -sn --since="2024-01-01"
29
30# Show total lines changed by author
31git shortlog -sn --numbered
32
33# Contribution statistics
34git diff --shortstat HEAD~10..HEAD
Visualizing History

Git provides both built-in visualization tools and integration with external GUI tools for exploring repository history.

terminal
Bash
1# ASCII graph visualization (built-in)
2git log --graph --oneline --all --decorate
3git log --graph --pretty=format:"%h %s%d" --all
4
5# Launch gitk (Tcl/Tk GUI browser)
6gitk
7gitk --all # show all branches
8gitk --since="2 weeks ago" # recent history
9
10# Launch git gui (basic GUI tool)
11git gui
12
13# External tools:
14# - GitKraken: cross-platform Git GUI
15# - Sourcetree: free Git GUI (Windows/Mac)
16# - VS Code GitLens extension
17# - GitHub Desktop
18
19# Custom pretty format for terminal visualization
20git log --graph --pretty=format:'%C(yellow)%h%Creset %C(cyan)%an%Creset %C(green)%ar%Creset%C(auto)%d%Creset %s'
21
22# Create an alias for daily use
23git config --global alias.tree "log --graph --oneline --all --decorate --simplify-by-decoration"
Best Practices

Master git log Aliases

Create aliases for your most-used log formats. A good default is git config --global alias.lg "log --oneline --graph --all --decorate". It makes browsing history effortless.

Use bisect Early and Often

When a bug appears, start a bisect immediately — the more commits you have, the more effective binary search is. Combine with git bisect run and an automated test for maximum efficiency.

Check Reflog Before Panicking

Accidentally reset to the wrong commit? Rebasing went wrong? The reflog has your back. Run git reflog to find the commit you were at and reset to it. Almost nothing in Git is permanently lost for 30 days.

Write Good Commit Messages

The power of git log --grep and git shortlog depends entirely on commit message quality. Invest in writing clear, descriptive commit messages that explain why a change was made.

$Blueprint — Engineering Documentation·Section ID: GIT-HIST·Revision: 1.0