Skip to content
masterclass Buddy

Git · Command

git log

git log shows commit history. It lists the commits you can reach from the starting points you give, newest first, and you can filter, order and format that list.

Last updated

How it works

Git starts from the revisions you name, or HEAD if you name none, and follows parent links back through history. Anything reachable from a revision marked with ^ (or placed after --not) is taken out of the result. The A..B form means ^A B, and A...B returns commits on either side but not both. Limiting options such as path filters, dates, authors and message patterns narrow that set. Ordering and formatting options then control how it prints. git log accepts git rev-list options for choosing commits and git diff options for showing each commit's changes.

Syntax

git log [<options>] [<revision-range>] [[--] <path>…]

Parameters

NameTypeDescription
<options>flagsOptions for limiting, simplifying, ordering and formatting commits, taken from rev-list, plus diff options that control how each commit's changes are shown.
<revision-range>revision rangeShows only commits in this range, for example origin..HEAD. If you leave it out, it defaults to HEAD, which is all history leading to the current commit.
[--] <path>…pathspecKeeps only the commits needed to explain how the matching files reached their current state. Put -- in front when a path could be confused with an option or a revision.

Returns

Prints the selected commits to standard output, newest first by default, in the chosen pretty format (medium by default). Diff output can be added with options such as -p or --stat.

Key points

  • Treat the arguments as set math. Start with every commit reachable from the positive revisions, then remove every commit reachable from the ones marked with ^.
  • A...B (three dots) lists commits that are on one side or the other but not both. Combine it with --left-only or --right-only to see a single side.
  • --follow keeps tracing a file's history back past renames, but it only accepts one file.
  • If you pass --grep more than once, a commit is kept when any pattern matches. Add --all-match to keep only commits that match every pattern.
  • --first-parent follows only the first parent of each merge. On a mainline branch this hides the individual commits that came in through merged topic branches.
  • --topo-order shows children before their parents and keeps parallel lines of development from being mixed together in the output.
  • -L<start>,<end>:<file> or -L:<funcname>:<file> follows how a range of lines or a single function changed over time. It turns on patch output automatically.

Common mistakes

  • Filters such as -n are applied before ordering. So git log -n 3 --reverse reverses the 3 newest commits; it does not show the 3 oldest.
  • --since stops walking at the first commit older than the date, so commits with out-of-order timestamps can be missed. --since-as-filter checks every commit in the range instead.
  • With -g/--walk-reflogs, git log walks reflog entries instead of ancestry, and you cannot use ^, .. or ... to exclude commits.
  • The default history simplification for a path can hide commits that really changed the file. Use --full-history, --simplify-merges or --show-pulls to see them.

Example: Review what your branch has that upstream lacks

#!/usr/bin/env bash
set -euo pipefail

# Commits on my branch that are not on origin/main, compact view
git log --oneline --no-merges origin/main..HEAD

# Same range, with per-file stats, only commits by me in the last 2 weeks
git log --stat --author="$(git config user.name)" --since="2 weeks ago" origin/main..HEAD

# History of one file, following renames, custom format
git log --follow --format='%h %ad %an %s' --date=short -- src/app.ts

# How a function evolved over time
git log -L :handleRequest:src/server.ts

# Mainline-only overview as a graph
git log --first-parent --graph --oneline -20

The script uses ranges, author and date filters, rename-following path history, function tracing with -L and a first-parent graph to show the most common ways to filter and format git log output.

When to use it

Pre-push review

Run git log origin/main..HEAD before pushing or opening a pull request to see exactly which local commits will go out.

Blame-style archaeology

Use --follow on one file, or -L on a function, to find when and why a piece of code changed, even if it was renamed.

Release notes

List the non-merge commits between two tags in a custom --format to draft a changelog.

Recovering lost work

Use git log -g to walk the reflog and find commits that no branch points to anymore after a reset or rebase.

Interview questions

QWhat is the difference between git log A..B and git log A...B?

A..B is shorthand for ^A B: it shows commits reachable from B but not from A, which is what B has that A doesn't. A...B is the symmetric difference: commits reachable from either side but not from both. That is the same as listing A and B and excluding their merge base(s).

Follow-up: How can you tell which side each commit in A...B came from? Add --left-right to mark commits with < or >, or use --left-only/--right-only to show one side; --cherry-pick also hides commits whose patch already exists on the other side.

QWhy might git log -- path miss a commit you know changed that file, and how do you fix it?

By default git log simplifies history. When a merge is TREESAME to one of its parents for that path, Git follows only that parent and never looks at the other side. Commits that only existed on that other side drop out. --full-history follows every parent, and --simplify-merges or --show-pulls cut that output down to the merges that actually matter.

Follow-up: What does --simplify-merges cost? Before it can print a single result it must walk the entire commit history, which makes it slow on very large repositories.

QHow would you list commits by a given author, from the last week, whose message mentions 'fix', in one line each?

Use git log --oneline --author=<pattern> --since='1 week ago' --grep=fix. Each extra limiting option narrows the result further. --author and --grep take regular expressions, and -i makes them case-insensitive.

Follow-up: If you pass two --grep patterns, does a commit need to match both? No. A match on any one pattern is enough by default; add --all-match to require all of them, or --invert-grep to keep commits that do not match.

  • git-rev-list
  • git-show
  • git-diff
  • git-shortlog
  • git-reflog
  • git-blame
  • gitrevisions
  • git-notes

Source: Git - git-log Documentation. Checked 2026-11-02.