View History with git log and diff
View history with git log and diff - Git Tutorial.
Focus: view history with git log and diff
You've committed your code with confidence, but now a bug appeared out of nowhere, or you need to understand why a change was made six months ago. Staring at the current state of your repository gives you no clues. Without the ability to look back in time, you're flying blind. This lesson shows you how to turn your Git repository into a time machine using git log and git diff, so you can answer 'what changed?', 'when?', and 'why?' with a few keystrokes.
The problem this lesson solves
Every developer has hit the same wall: you're debugging a regression, reviewing a teammate's pull request, or trying to figure out which commit introduced a breaking change. The answer is buried in your project's history. You might be tempted to scroll through file timestamps or rely on memory. That approach is slow, fragile, and completely unscalable.
Git stores every snapshot of your project, along with the author, date, and commit message. But raw storage is useless if you can't search it. git log lets you navigate the timeline of commits, while git diff shows the exact changes between any two points. Together, they give you a full forensic toolkit. Without them, you're debugging blindfolded.
Core concept / mental model
Think of your repository as a bushy tree of snapshots. Each commit is a node with a pointer to its parent. git log is like a flashlight that walks along that tree, highlighting each node. git diff is a magnifying glass that zooms in on the differences between two specific nodes.
A quick mental model:
git log= the timeline. Who did what, when, and the message they left behind.git diff= the zoom. Show me exactly which lines were added, removed, or modified between two commits, branches, or your working directory vs. the last commit.
Here's a simple ASCII diagram of a repo's history:
A --- B --- C --- D (main)
\
E --- F (feature)
git log shows you the commits in order (A, B, C, D on main). git diff B D shows the combined patch from B to D. git diff A C shows what changed between those two points. Master this, and you can compare anything.
How it works step by step
Let's break down the most common git log and git diff commands. You'll use these daily.
1. git log — the timeline
The most basic form:
git log
This shows a list of commits, newest first, with the full hash, author, date, and commit message. But that's a lot of output. You'll want to customize it.
Key flags to remember:
--oneline— condense each commit to a single line (hash + message).--graph— show the branch topology as ASCII art.--all— show commits from all branches, not just the current one.--author='name'— filter by author.--since='2 weeks ago'/--until='2024-01-01'— filter by date.-n 5or-5— limit to the last 5 commits.--grep='fix'— search commit messages for a pattern.
2. git diff — the zoom
git diff shows changes between different states. Common uses:
git diff— unstaged changes (working directory vs. index).git diff --staged— staged changes (index vs. last commit).git diff <commit>— changes between that commit and the working directory.git diff <commit1> <commit2>— changes between two commits.git diff --stat— summary of which files changed and how many lines.
When you run git diff, Git outputs a unified diff format. Lines starting with - are removals; + are additions. A line like @@ -10,5 +10,7 @@ tells you the position in the old and new file.
3. Combining them
You'll often want to see the last commit's changes. Use:
git log -p -1
This prints the log entry and the full diff for the last commit. Similarly, git show <commit> displays a single commit's details and its diff. It's a great one-liner for code review.
Hands-on walkthrough
Now let's get our hands dirty. We'll create a tiny repo, make a few commits, and practice with git log and git diff.
Setup a test repo
mkdir git-history-demo && cd git-history-demo
git init
echo "def add(a, b):\n return a + b" > calc.py
git add calc.py
git commit -m "Add add function"
echo "def subtract(a, b):\n return a - b" >> calc.py
git add calc.py
git commit -m "Add subtract function"
Now we have two commits. Let's examine the history.
View the log
git log --oneline
Expected output (hashes will differ):
2b1c6d4 Add subtract function
9a3f0e1 Add add function
Now let's see a more detailed view:
git log --stat
This adds a summary of files changed and line counts for each commit. Great for a quick overview.
See the changes in a commit
Use git show to view the second commit's diff:
git show 2b1c6d4
You'll see something like:
commit 2b1c6d4...
Author: You <you@example.com>
Date: ...
Add subtract function
diff --git a/calc.py b/calc.py
index 1111111..2222222 100644
--- a/calc.py
+++ b/calc.py
@@ -1,2 +1,4 @@
def add(a, b):
return a + b
+def subtract(a, b):
+ return a - b
Compare two commits directly
Now let's diff the first commit against the second:
git diff 9a3f0e1 2b1c6d4
You'll see the same output as git show because those are consecutive commits. But try this:
git diff 9a3f0e1 HEAD
HEAD is a pointer to the last commit on the current branch. It's a shortcut for the latest commit. This command shows the combined changes from the first commit to the latest.
Check working directory vs. last commit
Make an uncommitted change:
echo "def multiply(a, b):\n return a * b" >> calc.py
git diff
You'll see a diff showing the addition of the multiply function, but it's not yet staged. That's your safety net.
Filter the log
If you have many commits, you can filter:
git log --author="Alice" --oneline
git log --grep="bugfix" --oneline
git log --since="2024-01-01" --until="2024-02-01"
Now you can practice on your own repo. Try changing a file, committing, and then git diffing the new commit against the previous one.
Compare options / when to choose what
You have several ways to inspect history. Here's a quick comparison:
| Command | Purpose | When to use it |
|---|---|---|
git log |
List commits with metadata | Overview of the project's timeline |
git log --oneline |
Compact, one-line per commit | Daily quick glance |
git log -p |
Show commit diffs inline | Deep dive into a series of changes |
git show <commit> |
Single commit + its diff | Review a specific commit |
git diff |
Unstaged changes | Before staging, to see what you'll commit |
git diff --staged |
Staged changes vs. last commit | After git add, before commit |
git diff <c1> <c2> |
Changes between any two commits | Comparing branches or versions |
git diff --stat |
Summary of files changed | Quick stats, not details |
When to use what: Use git log --oneline for a quick scan, git show for a single commit's details, git diff to see uncommitted work, and git diff <c1> <c2> to compare large ranges like branch points.
Troubleshooting & edge cases
You'll inevitably run into a few confusing situations. Here's how to handle them:
Empty git diff output
You run git diff and see nothing. That means your working directory matches the index or last commit. If you expect changes, check if you've staged them with git status. If they're staged, git diff won't show them — use git diff --staged.
Too much output in git log
Long history can overwhelm you. Use git log --oneline -10 to see just the last 10 commits. Or pipe into less (which is the default) and press q to quit.
Merge commits are messy
When you git diff a merge commit, the output can be confusing because of two parents. Use git show <merge-commit> with -m to split into diffs against each parent:
git show -m <merge-commit>
Wrong author or date filters
If your --author filter returns nothing, verify the exact name or email. Git matches partial strings, but case matters. For dates, use the format --since='2 weeks ago' or --since='2024-03-01' (ISO format).
Path-specific diff
If you only care about a single file, add a path:
git diff <commit1> <commit2> -- calc.py
This narrows the output to just that file, which is huge, when you're searching through a large repo.
What you learned & what's next
You now have a solid grasp of viewing history with git log and git diff. Specifically, you learned to:
- Explain why history inspection is essential for debugging and collaboration.
- Use
git logwith common flags (--oneline,--graph,--author) to filter and format the timeline. - Apply
git diffto see unstaged, staged, and commit-to-commit changes. - Combine
git log -porgit showfor a deeper dive. - Compare options and choose the right command for the task.
- Troubleshoot common pitfalls like empty diffs and merge commit confusion.
These skills are foundational. Next, you'll dive into branching and merging, where you'll use git diff to compare branches before merging. You'll also learn how to resolve conflicts by inspecting the differences with git diff. Your history-viewing skills will be your compass as you navigate more complex workflows.
Continue to the next lesson in the Git Tutorial track to master branching.
Practice recap
Create a new branch in your demo repo, add a file, and commit it. Then run git diff main...your-branch to see exactly what your branch introduced. Finally, use git log --oneline --graph --all to visualize how your branch and main's history diverged. This hands-on exercise cements the difference between log and diff.
Common mistakes
- Running
git diffand expecting to see staged changes. Remember:git diffshows unstaged changes; usegit diff --stagedfor staged ones. - Forgetting to use
--onelineor a limit, and being overwhelmed by a hugegit logoutput. Always add-n 5or a filter to keep it manageable. - Thinking
git logandgit diffare interchangeable.git logis the timeline;git diffis the difference between points. They complement each other. - Using
git diffon a merge commit without-m, producing confusing combined output. Always add-mfor per-parent diffs. - Assuming
HEADmeans the latest commit on all branches.HEADis specific to your current branch; use--allingit logor branch names ingit diffto see other branches.
Variations
- Use
git diff --word-diffto see word-level changes instead of line-level, which is helpful for prose or configuration files. - Set up an alias like
git lgforgit log --oneline --graph --all --decorateto get a beautiful visual history with less typing. - Use
git diff --color-wordsor a GUI tool likegitkor VS Code's built-in source control panel for a more visual diff experience.
Real-world use cases
- Debugging a regression by using
git log -pto bisect which commit introduced the faulty line. - Reviewing a teammate's pull request by running
git diff main...featureto see only the changes the branch introduced. - Auditing a production incident by filtering
git log --since='2 weeks ago' --author='deploy-bot'to find suspect automated commits.
Key takeaways
git logis your timeline viewer: use--oneline,--all,--author, and--sinceto navigate history efficiently.git diffshows the exact changes: unstaged, staged, or between any two commits or branches.- Combine
git log -porgit show <commit>to see both the metadata and the patch for a specific commit. - Always check if changes are staged before running
git diff— it won't show staged changes. - For merge commits, use
git show -mto see diffs against each parent clearly. - Mastering diff output (unified format with
+/-and@@headers) is essential for code review and debugging.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.