29  29. Viewing History and Undoing Changes

Commits are only useful if you can look back at them and use them to undo mistakes. This page shows you how to read the history, see exactly what changed, and undo changes safely. It continues with the practice project from Your First Repository, which has two commits so far.

29.1 Viewing history: git log

git log

Output:

commit b90f840eb88afb1f49b39e019d369b3c837a311a (HEAD -> main)
Author: Maria Lopez <maria@example.com>
Date:   Tue Oct 6 10:22:00 2026 -0400

    Describe planned pages in README

commit ffd1f1f288e0fd9bcff8162ce43136cb6eb4318b
Author: Maria Lopez <maria@example.com>
Date:   Tue Oct 6 10:15:00 2026 -0400

    Add starter files for portfolio site

Each entry shows the full commit ID (hash), the author, the date, and the message. The newest commit is at the top. (HEAD -> main) marks where you are now: on the main branch, at its latest commit.

When the history is longer than your window, Git shows it in a scrollable viewer: use the arrow keys or Space to scroll, and press q to quit.

Some useful variations:

Command Shows
git log --oneline one line per commit: short ID and message
git log -3 only the 3 newest commits
git log --stat which files each commit changed, and how many lines

29.2 Seeing what changed: git diff

Open src/index.html in your text editor and replace the line <p>Under construction!</p> with these two lines, then save:

    <p>Hi, I'm Maria. I study business and build websites.</p>
    <p>Contact: maria@example.com</p>

Before you commit, ask Git what you changed:

git diff

Output:

diff --git a/src/index.html b/src/index.html
index ad87688..390be80 100644
--- a/src/index.html
+++ b/src/index.html
@@ -6,6 +6,7 @@
 </head>
 <body>
     <h1>Welcome to My Portfolio</h1>
-    <p>Under construction!</p>
+    <p>Hi, I'm Maria. I study business and build websites.</p>
+    <p>Contact: maria@example.com</p>
 </body>
 </html>

29.2.1 How to read a diff

  • --- a/src/index.html is the old version, +++ b/src/index.html the new one.
  • Lines starting with - were removed (red in the terminal); lines starting with + were added (green). Lines starting with a space are unchanged context, shown to help you find your place.
  • A changed line appears as a removed line followed by an added line.
  • @@ -6,6 +6,7 @@ says where you are in the file: the snippet starts at line 6 and is 6 lines long in the old version, and starts at line 6 and is 7 lines long in the new version. Sometimes Git adds a nearby line of the file after the second @@ as a landmark.
  • You can ignore the index ... line; it contains Git’s internal IDs.

29.2.2 git diff vs. git diff --staged

Stage the file and run git diff again:

git add src/index.html
git diff

This time there is no output. That’s because git diff compares your working directory with the staging area, and they are now the same. To see what you are about to commit, compare the staging area with the last commit:

git diff --staged

It prints the same diff as before. A diagram:

 working directory  <-- git diff -->  staging area  <-- git diff --staged -->  last commit

Now commit:

git commit -m "Add intro and contact email to home page"

Output:

[main 4293e1d] Add intro and contact email to home page
 1 file changed, 2 insertions(+), 1 deletion(-)

The history now has three commits:

git log --oneline

Output:

4293e1d (HEAD -> main) Add intro and contact email to home page
b90f840 Describe planned pages in README
ffd1f1f Add starter files for portfolio site

29.3 Looking at one commit: git show

git show followed by a commit ID prints that commit’s details and its diff. You only need the first few characters of the ID:

git show b90f840

Output:

commit b90f840eb88afb1f49b39e019d369b3c837a311a
Author: Maria Lopez <maria@example.com>
Date:   Tue Oct 6 10:22:00 2026 -0400

    Describe planned pages in README

diff --git a/README.md b/README.md
index 512dd88..9af11fc 100644
--- a/README.md
+++ b/README.md
@@ -5,3 +5,4 @@ This is a simple website project to learn Git!
 ## What it does

 A personal portfolio website.
+It will have a home page and a contact page.

git show without an ID shows the latest commit. (In Git, HEAD is a name for “the commit you are on now”, so git show HEAD does the same.)

29.4 Undoing changes

Which command you need depends on where the mistake is:

Situation Command Can you lose work?
Throw away uncommitted changes to a file git restore <file> Yes: those changes are gone for good
Unstage a file but keep your changes git restore --staged <file> No
Fix the last commit (message or a forgotten file) git commit --amend No, but only do it before you push
Undo a commit that is already in the history git revert <commit> No: it adds a new commit
Look at an old version of the whole project git switch --detach <commit> No (return with git switch main)

29.4.1 Throw away changes in a file: git restore

Maria wanted to add a line to README.md, but typed > instead of >>. The > overwrote the whole file:

echo "Contact page coming soon" > README.md
git diff

Output:

diff --git a/README.md b/README.md
index 9af11fc..b373488 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1 @@
-# My Awesome Project
-
-This is a simple website project to learn Git!
-
-## What it does
-
-A personal portfolio website.
-It will have a home page and a contact page.
+Contact page coming soon

Because the file was committed, Git can put it back:

git restore README.md
git status

Output:

On branch main
nothing to commit, working tree clean
git restore <file> can’t be undone

It replaces the file with the version in the staging area (which is usually the same as the last commit). Any uncommitted changes in that file are gone for good, because they were never saved in Git.

29.4.2 Unstage a file: git restore --staged

Maria writes a personal to-do list in notes.txt and, out of habit, runs git add .:

echo "call the bank, buy milk" > notes.txt
git add .
git status

Output:

On branch main
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    new file:   notes.txt

She doesn’t want it in the project, so she takes it out of the staging area:

git restore --staged notes.txt

git status now lists notes.txt under Untracked files again. The file itself is untouched. Maria then deletes it with rm notes.txt, because it doesn’t belong in the project folder. (To keep files like this out of git status for good, see .gitignore and Keeping Secrets Out of Git.)

29.4.3 Fix the last commit: git commit --amend

In css/style.css, Maria changes the h1 rule’s color: #333; to color: navy;, then commits with a typo in the message, and fixes it right away:

git add css/style.css
git commit -m "Make headng navy"
git commit --amend -m "Make heading navy"

Output (of the last command):

[main cb793da] Make heading navy
 Date: Wed Oct 7 14:20:00 2026 -0400
 1 file changed, 1 insertion(+), 1 deletion(-)

--amend replaces the last commit with a new one; notice the new ID. If you forgot to include a file, git add it and run git commit --amend --no-edit (which keeps the message).

Only amend commits you haven’t pushed to GitHub yet (pushing is covered in Putting Your Repository on GitHub). The online copy still has the old commit, and the two copies would disagree.

29.4.4 Undo a commit safely: git revert

Maria decides she doesn’t like the navy heading after all. git revert makes a new commit that does the exact opposite of an earlier one:

git revert --no-edit HEAD

Output:

[main fc2bb9b] Revert "Make heading navy"
 Date: Wed Oct 7 14:30:00 2026 -0400
 1 file changed, 1 insertion(+), 1 deletion(-)

HEAD means the latest commit; you can also give any commit ID, such as git revert cb793da. --no-edit accepts the ready-made message; without it, Git opens your editor so you can edit the message first. Both commits stay in the history, so nothing is lost, and it is safe even after you’ve pushed:

git log --oneline

Output:

fc2bb9b (HEAD -> main) Revert "Make heading navy"
cb793da Make heading navy
4293e1d Add intro and contact email to home page
b90f840 Describe planned pages in README
ffd1f1f Add starter files for portfolio site

29.5 Viewing an old version: git switch --detach

To see what the whole project looked like in an earlier commit, switch to it:

git switch --detach ffd1f1f

Output:

HEAD is now at ffd1f1f Add starter files for portfolio site

Your files now look exactly as they did in that commit: src/index.html says Under construction! again. git status reports HEAD detached at ffd1f1f. Detached HEAD means you are looking at a commit directly instead of being on a branch. Look around, run the site, but don’t make commits here.

Don’t panic if git log now shows only one commit: it lists history only up to where you are. The newer commits are safe. To return:

git switch main

Output:

Previous HEAD position was ffd1f1f Add starter files for portfolio site
Switched to branch 'main'

(git switch - also works: it goes back to the branch you were on before.)

Older tutorials, Stack Overflow answers, and AI tools often use older commands. git switch and git restore were added in 2019 (Git 2.23) to split up the jobs of git checkout, which did too many things.

Older command Modern equivalent
git checkout -- README.md git restore README.md
git reset HEAD README.md git restore --staged README.md
git checkout ffd1f1f git switch --detach ffd1f1f
git checkout main git switch main

Be very careful with git reset --hard. git reset --hard HEAD throws away all uncommitted changes in every file at once. git reset --hard HEAD~1 also deletes the latest commit from the branch (HEAD~1 means “one commit before HEAD”). If you’ve already pushed that commit, this causes trouble. If an AI suggests git reset --hard, make sure you understand exactly what it will throw away; git revert is usually the safer choice.

To bring back an old version of a single file without moving the whole project, use git restore with --source:

git restore --source=ffd1f1f src/index.html

The old version replaces the file in your working directory, and git status shows the file as modified. Commit it if you want to keep it, or run git restore src/index.html to go back to the current version.

Practice Questions

Easy

Question 1 · Multiple choice

Which command lists the commits compactly, one line per commit?

  1. git status
  2. git log --oneline
  3. git diff
  4. git show

b. git log --oneline prints a short ID and the message for each commit. git status (a) shows the state of your files, git diff (c) shows uncommitted changes, and git show (d) shows one commit in detail.

Question 2 · True or false

git log lists the oldest commit first.

False. The newest commit is at the top.

Question 3 · Short answer

Your project has 200 commits. You run git log and the output fills the screen in a viewer. How do you scroll, and how do you get back to the prompt?

Scroll with the arrow keys or Space, and press q to quit the viewer and return to the prompt.

Question 4 · Short answer

In the output of git diff, what do lines starting with +, -, and a space mean?

  • +: a line that was added.
  • -: a line that was removed.
  • a space: an unchanged line, shown as context.

A changed line appears as a - line followed by a + line.

Question 5 · Matching

Match each situation with the right command.

Situation Command
1. Throw away my uncommitted changes to README.md A. git revert <commit>
2. Take notes.txt out of the staging area B. git commit --amend -m "..."
3. Fix a typo in the last commit’s message (not pushed yet) C. git restore README.md
4. Undo an older commit with a new commit D. git switch --detach <commit>
5. Look at the whole project as it was in an old commit E. git restore --staged notes.txt

1 → C, 2 → E, 3 → B, 4 → A, 5 → D.

Question 6 · True or false

git restore --staged notes.txt deletes the file notes.txt.

False. It only takes the file out of the staging area. The file and its contents stay in your working directory; if it’s a new file, it simply becomes untracked again.

Medium

Question 7 · Read the diff

Describe in plain words what changed:

--- a/css/style.css
+++ b/css/style.css
@@ -4,5 +4,5 @@ body {
 }

 h1 {
-    color: #333;
+    color: navy;
 }

In css/style.css, the h1 rule’s color changed from #333 (dark gray) to navy. One line was removed and one added, which is how a diff shows a changed line. The rest are unchanged context lines.

Question 8 · Predict the output

Maria edits src/index.html and runs git add src/index.html. What do git diff and git diff --staged show now?

  • git diff shows nothing: it compares the working directory with the staging area, and they now match.
  • git diff --staged shows her change to src/index.html: it compares the staging area with the last commit, so it shows what she is about to commit.

Question 9 · Read the output

A diff contains the line @@ -10,4 +10,6 @@. What does it tell you?

The snippet starts at line 10 in both versions. It is 4 lines long in the old version and 6 lines long in the new version, so the change added two lines (overall) in that area.

Question 10 · Write the command

Write the command that shows the details and the diff of commit 4293e1d.

git show 4293e1d

Question 11 · Write the command

Maria just committed with the message Fix typo in hedaer. She hasn’t pushed. Write the command to change the message to Fix typo in header.

git commit --amend -m "Fix typo in header"

The last commit is replaced by a new one with the corrected message (and a new ID). This is fine because the commit hasn’t been pushed.

Question 12 · Multiple choice

A commit that broke the site was pushed to GitHub yesterday. Which is the safest way to undo it?

  1. git commit --amend
  2. git revert <commit>
  3. git restore <file>
  4. Delete the .git folder and start over

b. git revert adds a new commit that reverses the bad one, without rewriting history, so it’s safe after pushing. --amend (a) only changes the latest commit and rewrites it, which you shouldn’t do after pushing. git restore (c) only discards uncommitted changes. Deleting .git (d) destroys the whole history.

Question 13 · Ordering

Put these commands in order to look at the project as it was in commit ffd1f1f and then go back to normal work:

  • A. git switch main
  • B. git log --oneline (to find the commit ID)
  • C. git switch --detach ffd1f1f
  • D. look at the files (for example cat src/index.html)

B → C → D → A. Find the ID, switch to the old commit, look around, and switch back to main.

Question 14 · Scenario

Maria runs echo "New intro" > README.md, meaning to type >>. She hasn’t run git add or git commit since. How can she recover the file, and what will happen to the line New intro?

git restore README.md

This brings back the last committed version of README.md. The line New intro is thrown away (she can add it again, this time with >>). The recovery works only because the earlier contents had been committed.

Hard

Question 15 · Scenario

Same mistake as in the previous question, but this time Maria also ran git add . after overwriting README.md. She runs git restore README.md, but the file still says New intro. Why? How does she get the committed version back?

git restore README.md copies the file from the staging area, and the staging area now contains the bad version (she staged it with git add .). She must first unstage it, then restore it:

git restore --staged README.md
git restore README.md

(git restore --staged --worktree README.md does both in one command.) Now both the staging area and the working directory match the last commit.

Question 16 · Short answer

Why should you not use git commit --amend on a commit you’ve already pushed to GitHub?

--amend doesn’t edit the commit; it replaces it with a new commit that has a new ID. GitHub still has the old commit, so your local history and the online history no longer match, and Git will refuse a normal push. Fixing this requires more advanced (and risky) commands. After pushing, use git revert or simply make a new commit with the fix.

Question 17 · Scenario

Maria ran git switch --detach ffd1f1f. Now git log --oneline shows only one commit, and her contact email is gone from src/index.html. She thinks she has lost a week of work. Explain what’s going on and what she should do.

Nothing is lost. She is in detached HEAD state, looking at the old commit ffd1f1f. Her files show that old version, and git log only lists history up to where she is. All the newer commits are still in the repository. Running git switch main (or git switch -) brings back the latest version of every file and the full history.

Question 18 · Compare

Compare git restore <file> and git revert <commit>: what does each one undo, does it change the history, and can you lose work?

git restore <file> git revert <commit>
Undoes uncommitted changes in a file a change that is already committed
History not touched a new commit is added; nothing is removed
Risk the discarded changes are gone for good none: both the old commit and its reversal stay in the history

Question 19 · Find the bug

An AI chatbot told Maria: “To undo your last commit, run git reset --hard HEAD~1.” Her last commit is already on GitHub, and she also has unsaved (uncommitted) work in css/style.css. What would this command do? What should she use instead?

git reset --hard HEAD~1 would:

  1. remove the last commit from her main branch (rewriting history that GitHub already has, so her next normal push would be refused), and
  2. throw away all uncommitted changes in every file, including her work in css/style.css, which can’t be recovered with Git.

Safer: commit (or otherwise save) her work in css/style.css first, then run git revert <commit> with the bad commit’s ID from git log --oneline (after her new commit, the bad commit is no longer HEAD). This undoes the bad commit by adding a new commit.

Question 20 · Long answer

Explain the difference between git diff, git diff --staged, and git show. When would you use each one in your everyday workflow?

  • git diff: working directory vs. staging area, i.e. changes you haven’t staged yet. Use it while working, to review your edits (or an AI’s edits) before git add.
  • git diff --staged: staging area vs. last commit, i.e. exactly what the next commit will contain. Use it right before git commit.
  • git show <commit>: one commit that is already in the history, with its message and diff. Use it to understand what an earlier commit did.

© 2025-2026 Y. Rosenthal. All rights reserved.