Embercode
✕
Git and GitHubLesson 15 of 16

40 min read

Reading history: log filters and show

Why this matters

A project's history grows with every commit. A small website might have a few dozen commits after a month. A team project can pass a thousand in a year. Scrolling through all of them to find one change is slow and error-prone.

Two questions come up again and again. "Who changed the opening hours page last month?" and "What exactly did commit b7d3e90 change?" Git answers both with git log and git show. Lesson 3 covered the basic output of these commands, and lesson 4 showed git log --oneline --graph --all. This lesson covers the options that narrow the list, and the ways to look inside one commit.

The examples use a small practice project. Create it in a fresh folder, with commits made on different days. Your commit IDs will differ from the ones shown, so copy them from git log --oneline. The commands in this lesson do not change any history. They only read it, so you can try them freely.

Opening one commit with git show

git show prints one commit. By default it prints four things: the full commit ID, the author, the date, the message, and then the full diff of that commit. The diff is the same format you read in lesson 14.

You can name the commit in several ways:

  • The full ID, or the short ID from git log --oneline. Git accepts any prefix that is unique, so seven characters is usually enough.
  • HEAD for the latest commit, and HEAD~1 for the one before it.
  • A branch name or a tag name. git show main opens the commit that main points to.

Three options change what you see:

CommandWhat it prints
git show <id>The commit details and the full diff
git show --stat <id>The commit details and a list of changed files with counts
git show --name-only <id>The commit details and only the names of the changed files
git show -s <id>The commit details, with the diff left out

-s is short for --no-patch. It is the quickest way to read the message, author and date of a commit without the lines of code. Add --format to choose your own layout:

git show -s --format="%h %an %ad%n%s" --date=short HEAD

This prints the short ID, the author name, the date in short form, a newline (%n), and the subject. Lesson 3 showed %h, %an and %s. The new parts are %ad, which is the author date, and --date=short, which writes the date as 2026-10-21 instead of the full timestamp.

Use --stat first when you do not know a commit. It tells you which files changed and how much. Open the full diff only for the file you care about:

git show --stat b7d3e90
git show b7d3e90 -- menu.html

The second command limits the diff to one file. The -- separates the file name from the commit ID, so Git does not mistake the file name for a commit.

The filters that narrow git log

git log on its own lists every commit reachable from HEAD. Filters remove the commits you do not need. Each filter is a short option, and you can add several at once.

Filter by author

git log --author="Asha"

The pattern is matched against the author's name and email. It is a substring match, so Asha also matches Ashanti Rao, and asha@example.com only with -i. Use a longer pattern when a short one matches too much. The -i option makes the match ignore upper and lower case.

If you give --author twice, a commit matches when it fits either pattern:

git log --author="Asha" --author="Ravi"

Filter by date

git log --since=2026-10-01
git log --until=2026-10-31
git log --since=2026-10-01 --until=2026-10-31

--since keeps commits from that date onward. --until keeps commits up to that date. Use both to make a window. --after and --before are the same options with different names.

Use the form 2026-10-01, which is unambiguous. Git also accepts relative words such as --since="2 weeks ago", which is handy for "what happened this week". Avoid day-and-month forms such as 10/01/2026, because the same text can mean 1 October in one country and 10 January in another, and Git may not read it the way you meant.

Filter by message

git log --grep="menu"
git log -i --grep="fix"

--grep searches the commit message. The second command ignores case, so Fix, fix and FIX all match. It is a good way to find all the bug fixes, if your team writes messages that start with the word "Fix" (lesson 3 explained why good messages matter for this).

Filter by file or folder

Lesson 3 used one file name after --. You can give several paths, and a folder works as well:

git log --oneline -- menu.html
git log --oneline -- src/ docs/

The first command lists commits that touched menu.html. The second lists commits that touched anything inside src/ or docs/.

A file that was renamed has a shorter history under its new name. Add --follow to see the older commits too:

git log --follow --oneline -- menu.html

--follow works for one file at a time. Git follows the file back through its renames and lists the commits made under its old names.

Exclude merge commits

git log --no-merges --oneline

A merge commit (lesson 4) joins two lines of work and often has a message such as "Merge branch 'feature'". --no-merges removes those, so you see only the commits that carry real changes.

Range: between two points

Lesson 4 introduced the range syntax main..feature, which means "commits on feature that main does not have". The same syntax works with tags. For example, v1.0..HEAD lists the commits made since release v1.0 (lesson 12 covers tags). Combine a range with a filter when you need both:

git log --oneline --author="Ravi" v1.0..HEAD

Combining filters

Different kinds of filter combine with AND. A commit must pass all of them to be listed. Several values of the same kind combine with OR, so a commit passes if it matches any of them.

The rules are easier to see with data. The script below holds five commits from a made-up history of a café website, and applies the same filters you would use with git log. It is a toy: it is not Git, and the IDs are invented. Its only purpose is to show how the filters combine.

Python · editable

It prints:

author=Asha
  a1f0c22 2026-09-28 Asha Rao    Add home page
  c94a158 2026-10-10 Asha Rao    Add menu page
  e53b0ac 2026-11-01 Asha Rao    Fix menu prices
since 2026-10-01
  b7d3e90 2026-10-03 Ravi Kumar  Fix opening hours typo
  c94a158 2026-10-10 Asha Rao    Add menu page
  d2e6f71 2026-10-21 Ravi Kumar  Update footer
  e53b0ac 2026-11-01 Asha Rao    Fix menu prices
author=Asha AND since 2026-10-01
  c94a158 2026-10-10 Asha Rao    Add menu page
  e53b0ac 2026-11-01 Asha Rao    Fix menu prices
path=menu.html
  c94a158 2026-10-10 Asha Rao    Add menu page
  e53b0ac 2026-11-01 Asha Rao    Fix menu prices
grep=fix
  b7d3e90 2026-10-03 Ravi Kumar  Fix opening hours typo
  e53b0ac 2026-11-01 Asha Rao    Fix menu prices
path=menu.html AND grep=fix
  e53b0ac 2026-11-01 Asha Rao    Fix menu prices

Read the third block. author=Asha gives three commits, and since 2026-10-01 gives four. Only the commits that satisfy both appear in the third block, so the author filter and the date filter combine with AND. The last block works the same way with a file filter and a message filter.

The same logic applies to real git log commands:

git log --oneline --author="Asha" --since=2026-10-01

This lists only the commits by Asha made on or after 1 October. Each extra filter narrows the list further.

Showing what changed, for many commits

--stat adds the file summary to each commit in a list, which is useful when you are looking for a big change:

git log --stat -n 3

For each of the last three commits, this prints the commit details followed by a line for each changed file, with a count of lines added and removed. Lesson 3 showed the --stat summary for one commit, and this is the same summary on a list.

Two other options list only file names:

git log --name-only --oneline -n 3
git log --name-status --oneline -n 3

--name-only prints the names of the changed files. --name-status puts a letter before each name: A for a file added, M for modified, D for deleted, and R for renamed. The letters tell you what kind of change each commit made, and they are short enough to scan a long list.

Changing the layout of the list

Lesson 3 showed --format with three placeholders. The full set is long, but these are the ones most useful for reading history:

PlaceholderShows
%hShort commit ID
%anAuthor name
%adAuthor date (format controlled by --date)
%arAuthor date, relative (for example "3 days ago")
%sSubject, the first line of the message
git log --format="%h %ad %an %s" --date=short

Use --date=short for a compact date, --date=relative for "3 days ago", or leave the option out for the full timestamp.

A search from start to finish

A visitor says that the opening hours on the site were wrong for some time. You want to know when the hours changed, and what the change was. Use the filters to narrow the list, then look inside the best candidate.

Step 1. Find the commits that mention the hours. The message search is not exact, so use a broad word:

git log --oneline -i --grep="hours"

Step 2. Choose the likely commit from the list, and check which files it touched:

git show --stat b7d3e90

If the summary lists only index.html, the change is in the right place. If it lists ten files, the commit is probably a larger change, and the hours edit is one part of it.

Step 3. Read the change itself, limited to the one file:

git show b7d3e90 -- index.html

Step 4. Decide what you found. Compare the message with the diff. The message may say "Fix typo" while the diff also changes a number. The diff is the record of what happened. The message is only what the author wrote about it.

If the search finds nothing, the wording may have been different. Try --author to list one person's commits, then read each one's --stat in turn. For a few dozen commits this takes a minute, and it is often faster than guessing the right word.

Interview-style questions

  1. How do you list only the commits that changed one file? Use git log --oneline -- path/to/file. Add --follow to continue the history through renames.
  2. What does git show -s do? It hides the diff and shows only the commit details, so you can read the author, date and message quickly.
  3. Why do two filters on different things narrow the list, while two authors widen it? Different kinds of filter combine with AND, so a commit must pass each one. Two values of the same kind combine with OR, so either value is enough.

Common mistakes

1. Forgetting -- before a file name. If a file name is also the name of a branch or tag, or Git cannot tell that it is a path, you see a message like this:

fatal: ambiguous argument 'menu.html': both revision and filename
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Put -- before the file name, as in git log -- menu.html. The -- tells Git that everything after it is a path.

2. Giving a commit or branch that does not exist. Passing a name Git cannot find produces the same kind of message:

fatal: ambiguous argument 'nosuchbranch': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

Check the spelling with git branch (for branches) or git log --oneline (for commit IDs).

3. Assuming --author matches only the name. The filter also matches the email address, and it matches part of a word. A pattern of ravi matches ravi@example.com and Gravity Labs, but not Ravi Kumar unless you add -i. Put a longer or more exact pattern in the quotes when the list looks too long.

4. Running git log -p on a long history. The -p option prints the full diff of every commit in the list. On a project with hundreds of commits, that is thousands of lines. Use --stat, --name-only or a filter first, and add -p only to a short list. -n 5 limits the count.

5. Confusing --since with the date of the change. The filter compares each commit's date with the date you give. It does not look at the dates written inside the files. A commit made on 1 October about a change written a month earlier is listed under 1 October.

6. Reading git show as if it shows the whole project. git show shows one commit: the change, not the state of every file. To see a file as it was at a commit, use git show <id>:<path>, which lesson 3 covered.

Worked examples

Example 1: Find who last touched the menu. The menu lives in menu.html. Run git log --oneline -- menu.html. The first line of the output is the latest change to that file. Run git show --stat on that ID to see whether it changed only the menu or other files too.

Example 2: Find a fix made during October. Run git log --oneline -i --grep="fix" --since=2026-10-01 --until=2026-10-31. This combines a message filter and a date window. If the list is empty, widen the window or try a shorter word such as typo.

Example 3: See what one person did this week. Run git log --oneline --author="Ravi" --since="1 week ago". Then add --stat to see which files each change touched and how many lines moved.

Example 4: Find a commit that changed a folder. Your team moved the images to assets/. Run git log --oneline --follow -- assets/logo.png to find the commits that touched the logo. For a folder, drop --follow, since it works for one file, and run git log --oneline -- assets/.

Practice

Do these in a practice project with at least five commits. Try each before opening the answer.

Exercise 1 (easy). Show the message, author and date of the latest commit, without the diff.

Show the answer

git show -s HEAD. The -s option leaves out the diff. Add --format="%s %an %ad" --date=short to choose the fields.

Exercise 2 (easy). List only the commits that changed README.md.

Show the answer

git log --oneline -- README.md. The -- separates the file name from the options.

Exercise 3 (medium). List the commits whose message contains the word "fix", in any case, made since 1 October of this year.

Show the answer

git log --oneline -i --grep="fix" --since=2026-10-01. Replace the year and date with the ones you need. The -i makes the search ignore case, and both filters must match.

Exercise 4 (medium). Show the commit IDs and changed file names for the last three commits, one commit per block, without the line-by-line diff.

Show the answer

git log --name-only --oneline -n 3. The --name-only option prints the names of the changed files under each commit. The -n 3 limits the list to three commits.

Exercise 5 (hard). You want commits by either Asha or Ravi that changed menu.html. Write the command, then explain why a commit by Asha that did not touch menu.html is excluded.

Show the answer

git log --oneline --author="Asha" --author="Ravi" -- menu.html. The two --author options combine with OR, so a commit by either person matches. The file filter combines with AND, so the commit must also touch menu.html. A commit by Asha that changed only index.html fails the file filter and is left out.

Exercise 6 (hard). A teammate says git log --author="ravi kumar" returned nothing, but Ravi's commits exist. The author is Ravi Kumar. Why might the pattern fail, and what would you try?

Show the answer

The --author filter is case-sensitive by default, so ravi kumar does not match Ravi Kumar. Add -i to ignore case: git log -i --author="ravi kumar". If the pattern still fails, check the exact name with git log --format="%an" | sort -u and use that spelling.

Summary

  • git show opens one commit. Use --stat for a file summary, --name-only for file names, and -s to hide the diff.
  • --author, --since, --until, --grep and paths after -- narrow the list of commits.
  • Different kinds of filter combine with AND, and several values of the same kind combine with OR.
  • Use --follow to see a single file's history through renames.
  • --stat, --name-only and --name-status show what each commit changed, across a whole list.
  • Put -- before a file name whenever Git might confuse it with a branch or a commit.

Stuck? Ask the tutor

Ask about anything in this lesson. Answers are short and use simple words.

Sign in to ask the tutor.

← Reviewing changes with diff and staging hunks