Viewing History with git log
Every commit in a Git repository is a permanent, addressable snapshot linked to its parent, and git log is the primary tool for walking that chain backward from HEAD. By default it prints each commit's SHA-1 hash, author, date, and message in reverse chronological order, but the command becomes far more powerful once you learn its formatting and filtering flags. Understanding git log well is a prerequisite for almost every other Git skill: you cannot bisect, revert, cherry-pick, or write a good rebase plan without first being able to read history accurately.
Cricket analogy: Every commit is like a ball-by-ball entry in a match scorecard, permanently linked to the delivery before it, and git log is the commentator replaying the innings backward from the current ball to reconstruct exactly how the score reached its present state.
Basic usage and common flags
Running git log with no arguments shows the full commit chain reachable from HEAD, one entry per screen page. In practice, developers rarely use the bare command because full commit objects are verbose. The --oneline flag condenses each commit to an abbreviated hash and the first line of its message, making it easy to scan dozens of commits at once. Adding -n <count> (or just a number, e.g. -5) limits output to the most recent N commits, and --author=<pattern> or --since=/--until= narrow results by contributor or time window.
Cricket analogy: Bare git log is like reading a full ball-by-ball radio commentary transcript, which nobody has time for; --oneline is the newspaper's one-line scorecard summary, -5 limits it to the last five overs, and --author=/--since= filters to one bowler's spell in a given session.
Visualizing branch topology
Because a repository's history is a directed acyclic graph rather than a straight line, plain git log output can hide the fact that branches diverged and merged. The --graph flag draws ASCII lines connecting each commit to its parents, and combined with --all (show every ref, not just HEAD's ancestry) and --decorate (label commits with branch and tag names) it produces a readable map of the whole project. This three-flag combination is common enough that many teams alias it: git config --global alias.lg 'log --graph --oneline --all --decorate'.
Cricket analogy: Because a tournament's results form a bracket rather than a single sequence, plain results-listing hides which teams' paths crossed; --graph draws the bracket tree, --all includes every group not just the finalists' path, and --decorate labels each match with the trophy or milestone reached — a combination worth saving as a quick-access alias.
# Compact, graphical view of all branches
$ git log --graph --oneline --all --decorate
* a1b2c3d (HEAD -> main, origin/main) Merge branch 'feature/checkout'
|\
| * 9f8e7d6 (feature/checkout) Add promo code validation
| * 5c4b3a2 Wire checkout form to payment API
|/
* 7d6e5f4 Fix off-by-one error in pagination
# Show file-level diffs alongside each commit
$ git log -p -- src/checkout.py
# Find commits whose message OR diff mentions "payment"
$ git log --oneline --grep="payment" -i
# Custom, script-friendly format
$ git log --pretty=format:'%h | %an | %ad | %s' --date=short -10Filtering by path, content, and range
Appending -- <path> after any log command restricts results to commits that touched that file or directory, which is invaluable when tracing the history of a single module in a large repository. The -S<string> option (the "pickaxe") goes further, showing only commits that changed the number of occurrences of a given string — useful for finding when a function was introduced or removed. Range syntax like git log main..feature shows commits reachable from feature but not main, which is exactly what a reviewer sees before merging a pull request.
Cricket analogy: -- <path> is like filtering match archives to only games played at one specific stadium, useful for tracing that venue's history; -S<string> is a pickaxe search for exactly when a bowler's signature delivery first appeared in the records; main..feature shows only the new spell a bowler bowled that the main squad hasn't seen yet.
The abbreviated hash Git prints (e.g. a1b2c3d) is not fixed-length by convention; Git shows the shortest prefix that remains unambiguous in the current repository, expanding it automatically as the object database grows and collisions become more likely.
git log output can be paginated through less by default. If a command appears to "hang" in a script or CI log, it's often just waiting at a pager prompt — pass --no-pager (or git --no-pager log) in non-interactive contexts to avoid this.
git logwalks the commit graph backward from HEAD, printing hash, author, date, and message by default.--oneline,-n,--author, and--since/--untilare the most common ways to trim noisy output.--graph --decorate --allreveals branch topology instead of a flattened linear view.-- <path>restricts history to a file or directory;-S<string>finds commits that added or removed a specific string.- Range syntax like
main..featureshows commits unique to one branch relative to another — the basis of PR diff review. - Use
--no-pagerin scripts and CI to avoid blocking on an interactive pager.
Practice what you learned
1. Which flag causes `git log` to draw ASCII lines representing branch and merge topology?
2. What does `git log main..feature` show?
3. Which option restricts `git log` output to commits that changed the number of occurrences of a specific string in the diff?
4. By default, what does `git log` order commits by?
5. Why might `git log` appear to hang in a non-interactive CI script?
Was this page helpful?
You May Also Like
The Three States of Git
Understand Git's core mental model — working directory, staging area, and repository — and how files move between them during a typical edit-commit cycle.
Committing Changes
How to create commits, write effective commit messages, and understand what a commit actually records in Git's history.
git bisect for Debugging
Learn how git bisect uses binary search over your commit history to pinpoint exactly which commit introduced a bug, dramatically faster than checking commits one by one.
Recovering Lost Commits with reflog
Discover how git's reflog silently tracks every movement of HEAD and branch tips, giving you a safety net to recover commits after resets, rebases, or accidental deletions.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringTesting & TDD Study Notes
Software Testing · 30 topics
Software EngineeringDesign Patterns Study Notes
Software Design · 30 topics
Software EngineeringSoftware Engineering Study Notes
Python · 40 topics
Software EngineeringSystem Design Study Notes
Architecture · 40 topics