Tutorial 7 of 8
Reading and Fixing History
Find who changed what and when, and undo a bad commit without rewriting history.
About 6 minutes
What you will be able to do
- Use git show to read a commit's author, date, message and changes.
- Filter git log by author and by dates, and limit it to the last few commits with -n.
- Undo a commit's changes with git revert <id>, including a merge commit with -m 1, and explain why revert is safe on shared branches.
Title
Reading and Fixing History. Ask the history questions, then undo safely.
This tutorial shows how to search your history and how to undo a commit by adding a new one.
Analogy: reading a photo's caption
git show <id> displays one commit: its author, date, message and the exact changes.
git show 3d88f33
git show prints one commit's details and its changes, and it shows HEAD if you do not give an ID.
Turning a photo over to read the caption on the back: who took it, when, and what it shows.
The date shown is the author date, when the change was first written, and a commit also has a separate committer date that can differ after a rebase or cherry-pick.
Just the summary
Too much output? Add --stat for a list of changed files, or -s to hide the changes.
git show --stat 3d88f33 # which files changed, and how much git show -s 3d88f33 # author, date and message only git show # the commit HEAD is on
Options like --stat and -s (short for --no-patch) trim git show down to the part you need.
The last five commits
git log -n 5 shows only the five newest commits.
git log -n 5 --oneline
The -n option limits how many commits git log prints, and git log always starts with the newest.
Analogy: searching a checkout register
Filter by person with --author. Git searches the author's name and email.
git log --author="JohnDoe" --oneline
The --author option keeps only commits whose author name or email matches your pattern.
Like searching a library's checkout register for every entry with one member's name.
A register search usually matches the exact name, but --author treats your text as a pattern, so JohnDoe also matches JohnDoeJr, and it checks the author, not the committer.
Between two dates
Add --since and --until to see commits between two dates.
git log --author="JohnDoe" --since="2025-01-01" --until="2025-12-31"
Combining --author with --since and --until narrows the log to one person's work in a date range.
Two tips for exact searches
A date without a time uses the current clock time. Add times for exact edges. Anchor a name to match only that name.
git log --author="JohnDoe" --since="2025-01-01 00:00:00" --until="2025-12-31 23:59:59" git log --author="^JohnDoe <" # JohnDoe only, not JohnDoeJr
Adding explicit times and anchoring the author pattern makes your search match exactly what you mean.
Analogy: a newspaper correction
git revert <id> makes a new commit that undoes that commit's changes. Nothing is deleted.
Revert keeps the mistake in history and adds a new commit that cancels its effect.
A newspaper does not recall yesterday's papers; it prints a correction in today's issue.
A printed correction is written by hand, but git revert works out the exact opposite changes for you, and if later commits changed the same lines you must fix a conflict.
Revert a commit
Git writes the message for you and names the commit it undoes. Add --no-edit to skip the editor.
git log --oneline -n 3 git revert 3d88f33 # or, without opening an editor: git revert --no-edit 3d88f33
git revert needs a clean working folder, then creates the undo commit with a ready-made message.
Reverting a merge needs -m
Reverting a merge commit? Tell Git which parent is the main line with -m 1.
git revert 932d4df # error: commit 932d4df... is a merge but no -m option was given. git revert -m 1 932d4df
A merge has two parents, so git revert needs -m to know which side to keep, and -m 1 keeps the main line.
Why revert on shared branches
On shared branches, prefer revert. It adds history instead of rewriting it, so teammates stay in sync.
Because revert only adds a commit, everyone can pull it normally, unlike commands that remove commits from shared history.
Recap
show reads one commit. log filters by author and dates. -n limits the list. revert adds an undo commit. Merges need -m.
Authors in this repo: JohnDoe, JohnDoeJr, Priya $ git log --author="JohnDoe" --oneline
You can now answer history questions and undo mistakes safely, and next you will make your first open-source contribution.
Check yourself
0 of 5 answered
Check 1 of 5
Which command shows one commit's author, date, message and changes?
Check 2 of 5
Whose commits does this command list?
Authors in this repo: JohnDoe, JohnDoeJr, Priya $ git log --author="JohnDoe" --oneline
Check 3 of 5
You want to see only the last five commits. Which command do you use?
Check 4 of 5
Click the commit that now holds the undo of C2's changes.
Before: main has C1, C2, C3, C4. After running git revert C2, the graph shows C1, C2, C3, C4 and a new commit R1 after C4.
Check 5 of 5
git revert <merge-id> fails with "is a merge but no -m option was given". What should you run?
mkdir -p ~/git-practice/t07-history && cd ~/git-practice/t07-history git init -b main export GIT_AUTHOR_DATE="2024-12-20T10:00:00" GIT_COMMITTER_DATE="2024-12-20T10:00:00" echo "price = 100" > cart.txt && git add cart.txt git commit --author="JohnDoe <john@example.com>" -m "Add cart" export GIT_AUTHOR_DATE="2025-03-10T10:00:00" GIT_COMMITTER_DATE="2025-03-10T10:00:00" echo "discount = 10" >> cart.txt && git add cart.txt git commit --author="Priya <priya@example.com>" -m "Add discount" export GIT_AUTHOR_DATE="2025-06-15T10:00:00" GIT_COMMITTER_DATE="2025-06-15T10:00:00" echo "discount = 90" >> cart.txt && git add cart.txt git commit --author="JohnDoe <john@example.com>" -m "Add bad discount" export GIT_AUTHOR_DATE="2025-08-01T10:00:00" GIT_COMMITTER_DATE="2025-08-01T10:00:00" echo "tax = 18" > tax.txt && git add tax.txt git commit --author="JohnDoeJr <jr@example.com>" -m "Add tax" unset GIT_AUTHOR_DATE GIT_COMMITTER_DATE # back to real dates git log -n 5 --oneline git log --author="JohnDoe" --oneline # includes JohnDoeJr git log --author="JohnDoe" --since="2025-01-01" --until="2025-12-31" --oneline git show HEAD~1 # HEAD~1 is the commit before HEAD; press q to leave git revert --no-edit HEAD~1 # undo "Add bad discount" cat cart.txt # the discount = 90 line is gone git log --oneline -n 3 # Optional: reverting a merge git switch -c feature echo "extra" > extra.txt && git add extra.txt && git commit -m "Add extra" git switch main git merge --no-ff -m "Merge feature" feature git revert HEAD # fails: a merge needs -m git revert --no-edit -m 1 HEAD # works: extra.txt is removed