Read Git History Without Losing the Thread
By the end of this guide you will be able to use git log to answer practical history questions: what changed recently, which commits are on your branch, who touched a file, and where a line came from. The examples use Git 2.43.0, the version installed with the local git-man package. Allow about 10 minutes for the first pass. You need a Git working tree and ordinary read access to it. None of the commands below needs elevated privileges.
The route
Jump straight to the step you need, or tick off Done means at the end.
1. Start with a readable recent log
Change to the repository you want to inspect, then ask for the latest commits in compact form:
cd /path/to/repository
git log --oneline --decorate -n 12
--oneline is a shorthand for a compact commit ID and subject. --decorate adds useful names such as HEAD, branch names and tags. The default order is reverse chronological: the newest reachable commit appears first. -n 12 limits the result to twelve commits, so a large repository does not immediately fill your terminal.
Expected output has one commit per line, although the exact IDs and subjects depend on the repository:
7f3a1c2 (HEAD -> main) Document the backup check
2b91e44 (tag: v1.4.0) Release 1.4.0
...
Checkpoint
If this prints commits, the repository is ready for the narrower searches below. If Git says it is not a repository, repeat cd with the directory containing its .git data.
2. See the branch relationship
To see branches and merges as a map, add --graph and include all local refs:
git log --oneline --decorate --graph --all -n 30
--all includes commits reachable from all local and remote-tracking references known to this checkout. The graph characters show the parent links; they are not a chronological table. The output can be busy in an active repository, so start with a small -n value and increase it only when you need more context.
To ask what is on your current branch but not on a remote-tracking branch, use the two-dot range:
git log --oneline origin/main..HEAD
This means commits reachable from HEAD after excluding commits reachable from origin/main. An empty result means this checkout has no commits in that direction. It does not prove that the remote is up to date; the name is only as current as the last fetch.
3. Narrow history by file or directory
Put -- before a path when you want commits that touched it:
git log --oneline --follow -- src/config.toml
The separator prevents a path from being confused with a revision or option. --follow continues a single file's history across renames. It works only with one file, so omit it for a directory or multiple paths:
git log --oneline -- src/ tests/
A path limits which commits are listed. It does not, by itself, show the patch. Add -p when you need the actual diff:
git log -p -n 3 -- src/config.toml
With a path, the patch is normally limited to that path as well. --full-diff keeps the commit selection limited by the path but shows the full diff for each selected commit. This distinction matters when a commit changed several files and you need to understand its complete change.
4. Find commits by person, date or message
Use independent filters together to reduce a long history to a useful set:
git log --oneline --author='Alex Example' --since='2026-01-01' --grep='backup' --regexp-ignore-case
--author matches an author pattern, while --committer filters the committer instead. They are not always the same person. --since and its alias --after keep commits after a date; --until and --before provide the other boundary. --grep searches commit messages. Message matching is case-sensitive unless you add --regexp-ignore-case, as above.
For a quick count or first result, combine the filters with a limit:
git log --format='%h %ad %an %s' --date=short --since='30 days ago' -n 20
The --format string controls each line: abbreviated hash, short author date, author name and subject. If you need machine-readable output, choose a format deliberately and avoid parsing the default multi-line display.
5. Inspect one commit safely
Once a log gives you a commit ID, inspect it without changing the worktree:
git show --stat --summary 7f3a1c2
git show --format=fuller --find-renames 7f3a1c2
The first command gives a compact file summary. The second shows the commit metadata and patch, and asks Git to detect renames while displaying it. Replace the example ID with one from your own log. git log can also show patches with -p, but git show is usually the clearer tool once you have selected one object.
To trace a particular line range in one file, use -L:
git log -L 20,45:src/config.toml
This follows the evolution of lines 20 to 45 from a single starting revision and implies patch output. It cannot be combined with a path limiter, and the specified lines must exist in the starting revision. Use it for a focused investigation, not as a general replacement for a file log.
6. Avoid the common interpretation traps
- Reachability is not just a date search. A normal log walks parent links from the revisions you name. A commit on another branch is absent unless that branch is reachable from the starting revision or you include it with
--allor an explicit ref. - Ranges are set operations.
A..Bmeans B excluding commits reachable from A.A...Bshows the symmetric difference, which is useful for comparing two lines of development around their merge base. - Paths come after revisions. Without
--, a name can be interpreted as a revision. With it, everything after the separator is a path specification. - Names can be stale. If
origin/mainmatters, fetch first and then repeat the log. Fetching updates remote-tracking refs but does not rewrite your commits or merge anything into your branch. - Formatting changes the display, not history. Options such as
--oneline,--pretty,--dateand--decorateaffect what you see. They do not alter commits.
7. Verify the question you actually answered
Before recording a result in a ticket or release note, rerun the command with an explicit revision and path where possible:
git log --format='%H %ad %an %s' --date=iso-strict origin/main..HEAD -- src/
git rev-parse --show-toplevel
The first command makes the complete commit IDs and date format visible. The second confirms which working tree you inspected. If the range is empty, say so rather than treating an empty display as a command failure. If you need current remote state, run git fetch origin only when that network operation is acceptable, then rerun the comparison. Nothing in this guide writes files, resets refs or discards work, so there is no undo operation required.
Done means
- You can produce a short, decorated recent log.
- You can explain what each side of a two-dot range includes.
- You can filter by file, author, date and commit message without confusing paths with revisions.
- You can inspect a selected commit or line range without changing the working tree.
- You verify the repository and range before relying on the result.