Reading History
Git history is not just a museum of old work. It is a search interface for decisions: what changed, who changed it, why it probably changed, and which line of development carried it in.
History as Questions
After you have more than a few commits, the important skill is not memorizing every git log option. It is learning to ask the right question and choose the smallest history view that answers it.
A repository's commit history is the chain, or graph, of snapshots reachable from a starting point such as HEAD, a branch name, or a tag. Each commit records a tree of files, a message, author metadata, committer metadata, and links to its parent commit or commits.
Most daily history reading falls into five questions:
- What happened recently? Use a short log.
- What exactly did this commit change? Use
git show. - Where did this branch split or merge? Use a graph view.
- When did this file or behavior change? Limit the log by path or message.
- What is on one branch but not another? Use a commit range.
Git commands often look dense because they combine these questions. For example, git log --oneline --graph --decorate --all means: show a compact list, draw branch shape, label refs, and do not restrict the view to the current branch.
The Plain Log
The default command is intentionally verbose:
git log
With no extra arguments, git log lists commits reachable from HEAD, newest first. A typical entry shows the full object name, author, date, and commit message. That is useful when you need exact metadata, but it is too tall for browsing a busy project.
| Field | What it tells you | Beginner reading habit |
|---|---|---|
commit |
The commit object's full hash. | Use the first several characters when copying a commit name for git show. |
Author |
The person credited with writing the change. | Do not assume the author is the person who merged it; Git tracks author and committer separately. |
Date |
The author date in the default output. | Use date filters when you care about a time window, not manual scrolling. |
| Message | The human explanation attached to the snapshot. | Treat the subject line as a clue, then inspect the patch before trusting it fully. |
Limit early and often. If the screen fills with too much history, ask for fewer commits:
git log -5
Read history from the newest relevant commit backward. Git defaults to newest-first because most investigations start with "what changed recently?" rather than "what happened at the beginning of the project?"
Compact Views
The shortest useful history view is usually --oneline. It abbreviates the commit hash and prints the subject on one line:
git log --oneline
For a branch with merges, add --graph and --decorate:
git log --oneline --graph --decorate
--graph draws an ASCII graph beside the commits. --decorate shows ref names such as branch names and tags. Add --all when you want the graph to include every local ref, not just commits reachable from your current checkout:
git log --oneline --graph --decorate --all
You can also choose exactly what each line prints. This format is friendly for daily review because it includes the short hash, relative date, author, and subject:
git log --pretty=format:"%h %ar %an %s"
When you are looking for file impact instead of branch shape, --stat gives a per-commit summary of changed files and line counts:
git log --stat -3
Show One Commit
git log answers "which commits are in this history?" git show answers "what is this object?" For a commit, that usually means metadata plus the patch introduced by the commit.
git show a1b2c3d
You can name the current commit as HEAD, its parent as HEAD^, and earlier ancestors with forms such as HEAD~2. At this stage, think of those as convenient relative names: "the commit I am on," "its first parent," and "two first-parent steps back."
git show HEAD
git show HEAD^
git show HEAD~2
Use --name-only or --stat when the patch is too detailed for the first pass:
git show --name-only a1b2c3d
git show --stat a1b2c3d
Good history reading alternates between list view and object view. Use git log --oneline to find a candidate commit, then git show to inspect it before drawing conclusions.
Limit the Search
History gets useful when you stop reading all of it. Git can limit logs by path, author, date, message text, and even by changes that add or remove a particular string.
Path-limited history
To ask "what commits touched this file or directory?", put the path after --:
git log --oneline -- src/app.js
The separator matters because branch names, commit names, and paths can overlap. -- tells Git, "the revision arguments are finished; what follows is a pathspec."
Author, date, and message filters
These filters make quick work of common investigations:
git log --author="Mina"
git log --since="2026-05-01" --until="2026-05-19"
git log --grep="login"
git log --oneline --author="Mina" --grep="cache"
--author matches author identity, not necessarily the person who committed or merged the change. --grep searches commit messages. For the actual patch text, use pickaxe search:
git log -S"calculateTotal" -- src/
-S is useful when a function, constant, error message, or configuration key appeared or disappeared. It is more targeted than message search because it searches the changes themselves.
Commit Ranges
A commit range compares reachability. That sounds abstract, but the beginner use is simple: "show me commits reachable from one name that are not reachable from another."
A..BThe range A..B means commits reachable from B excluding commits reachable from A. In daily branch work, read it as "what is on B that is not already on A?"
git log --oneline main..feature
The direction is the part worth practicing. main..feature points at feature. Switch the names and you ask the opposite question:
git log --oneline main..feature
git log --oneline feature..main
You will also see the three-dot form, A...B. At an introductory level, treat it as a branch-comparison view: commits reachable from either side, but not from both. It is useful for seeing divergence, while two-dot ranges are better for "what would be introduced if this branch were merged?"
Before merging or opening a pull request, run git log --oneline main..HEAD. It shows the commits your current branch contributes relative to main.
Which View to Use
There is no prize for the longest command. Pick the view that answers the question with the least noise.
Daily orientation
Use git log --oneline -10 to see the recent story without drowning in metadata.
Branch shape
Use git log --oneline --graph --decorate --all when merges, branches, or tags matter.
One commit
Use git show <commit> when you need the patch and message for a specific commit.
One file
Use git log -- <path> when the project history is too broad but the file is known.
One person or phrase
Use --author, --grep, or -S depending on whether the clue is identity, message, or changed text.
One branch delta
Use base..branch to see commits the branch has that the base does not.
Common Pitfalls
Reading only commit messages. A message is a map, not the territory. If the exact behavior matters, follow a promising log entry with git show or git show --stat.
Forgetting the -- before paths. Use git log -- path/to/file for path-limited history. The separator prevents ambiguous names from being interpreted as revisions.
Reversing two-dot ranges. main..feature and feature..main answer opposite questions. Read A..B as "reachable from B, excluding A."
Expecting --author to mean "who merged this." Author and committer are different metadata fields. If a patch was applied by someone else, the author can name the original writer while the committer records who applied it.
Worked Examples
Try choosing the command before you open each answer. The goal is to build a small decision tree, not to memorize a giant option list.
Example 1: You want the recent story of your current branch
Start compact, then expand only if something looks suspicious.
git log --oneline -10
If one commit needs inspection, copy its short hash and run:
git show a1b2c3d
Example 2: You need to know when a file changed
Limit by path first. This removes commits that did not touch the file.
git log --oneline -- config/settings.yml
If the file changed many times, add date or message filters:
git log --oneline --since="2026-05-01" --grep="cache" -- config/settings.yml
Example 3: You want to review what your branch will contribute
Use a two-dot range from the base branch to your current branch. If you are currently on the feature branch, HEAD is enough.
git log --oneline main..HEAD
For a richer review, add stats:
git log --stat main..HEAD
Example 4: You remember a function name but not the commit
Search the patch history with -S. This finds commits where the number of occurrences of that string changed.
git log -S"normalizeEmail" -- src/
When you find a likely commit, inspect it:
git show a1b2c3d
Example 5: You want to see who contributed to a release window
git shortlog summarizes commits by author. It is a reporting view, not an inspection view.
git shortlog -sn v1.2.0..v1.3.0
Use this after you already know the range you care about. For individual commits, go back to git log or git show.
Sources & further reading
-
The clearest official introduction to
git log, including patch output, statistics, pretty formats, and graph output. -
The complete reference for log options, filtering, formatting, path limiting, revision arguments, and history simplification.
-
Use this when you want the precise behavior of
git showfor commits, tags, trees, blobs, and formatting options. -
The formal reference for naming commits and ranges, including
HEAD, parent syntax, two-dot ranges, and three-dot ranges. -
A compact reference for summarizing commit logs by author, especially useful for release notes and contribution summaries.