View History with git log and diff

View history with git log and diff - Git Tutorial.

Focus: view history with git log and diff

Sponsored

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 5 or -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 log with common flags (--oneline, --graph, --author) to filter and format the timeline.
  • Apply git diff to see unstaged, staged, and commit-to-commit changes.
  • Combine git log -p or git show for 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 diff and expecting to see staged changes. Remember: git diff shows unstaged changes; use git diff --staged for staged ones.
  • Forgetting to use --oneline or a limit, and being overwhelmed by a huge git log output. Always add -n 5 or a filter to keep it manageable.
  • Thinking git log and git diff are interchangeable. git log is the timeline; git diff is the difference between points. They complement each other.
  • Using git diff on a merge commit without -m, producing confusing combined output. Always add -m for per-parent diffs.
  • Assuming HEAD means the latest commit on all branches. HEAD is specific to your current branch; use --all in git log or branch names in git diff to see other branches.

Variations

  1. Use git diff --word-diff to see word-level changes instead of line-level, which is helpful for prose or configuration files.
  2. Set up an alias like git lg for git log --oneline --graph --all --decorate to get a beautiful visual history with less typing.
  3. Use git diff --color-words or a GUI tool like gitk or 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 -p to bisect which commit introduced the faulty line.
  • Reviewing a teammate's pull request by running git diff main...feature to 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 log is your timeline viewer: use --oneline, --all, --author, and --since to navigate history efficiently.
  • git diff shows the exact changes: unstaged, staged, or between any two commits or branches.
  • Combine git log -p or git 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 -m to see diffs against each parent clearly.
  • Mastering diff output (unified format with +/- and @@ headers) is essential for code review and debugging.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.