100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Bash

Viewing History with git log

Learn to inspect a repository's commit history using git log's filtering, formatting, and graph options to understand who changed what and why.

The Basic WorkflowBeginner8 min readJul 9, 2026
Analogies

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.

bash
# 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 -10

Filtering 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 log walks the commit graph backward from HEAD, printing hash, author, date, and message by default.
  • --oneline, -n, --author, and --since/--until are the most common ways to trim noisy output.
  • --graph --decorate --all reveals 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..feature shows commits unique to one branch relative to another — the basis of PR diff review.
  • Use --no-pager in scripts and CI to avoid blocking on an interactive pager.

Practice what you learned

Was this page helpful?

Topics covered

#Bash#GitVersionControlStudyNotes#SoftwareEngineering#ViewingHistoryWithGitLog#Viewing#History#Git#Log#StudyNotes#SkillVeris