Unit 10 · lesson
Read Git History Like Evidence
Core path: 30 minutes
A Git repository is not just a place where old versions go to die.
It is a timeline of claims about how the project changed.
If the history is useful, you can answer questions such as:
- When did this feature appear?
- Which commit introduced this line?
- What changed between two checkpoints?
- Is my working tree different from the last commit?
- Did I push the commit I think I pushed?
That is why Git belongs in a development course, not just a collaboration unit.
Start with the three states you already know
Your project can contain:
WORKING TREE
changes you are editing now
STAGING AREA
changes selected for the next commit
COMMIT HISTORY
recorded checkpoints
The Ghostty terminal simulation in this week should make that state visible in the prompt:
!1 modified
+1 staged
↑1 local commit not yet pushed
✓ synchronized / clean state in the simulation
Those symbols are not decoration. They are a compact status report.
Inspect the present before reading the past
Run:
git status
Then:
git diff
git status tells you which paths are different and what state they are in.
git diff shows the content differences that are not staged by default.
If you stage a file:
git add main.py
then compare:
git diff
git diff --staged
The first may become empty for that file because the change moved out of the unstaged working-tree diff. The second shows what is waiting to become part of the next commit.
That is a much stronger mental model than "git add saves the file." It does not.
Ask a commit what it changed
Use:
git log --oneline
Choose one commit hash from your Lesson 4 project.
Then inspect it:
git show <commit-hash>
You should see the commit metadata and patch.
Now the commit message is no longer the only story. The actual diff is evidence.
A message can say Fix player search while the patch also rewrites three unrelated files. Read the patch.
Compare two checkpoints
Suppose your history contains:
c3 Add player search
b2 Add roster display
You can compare them:
git diff b2 c3
The exact hashes on your machine will differ.
The question is:
What changed between these two recorded states?
Git can answer that directly.
Recovery starts with identifying the state you want
Imagine you edit main.py and realize the current uncommitted experiment is bad.
Before using any recovery command, answer:
- Is the bad change committed or uncommitted?
- Is it staged?
- Is there work in the file you still need?
- Which known-good state are you trying to return to?
For a disposable unstaged change to one file, a command such as:
git restore main.py
can replace the working-tree copy with the version from the index/HEAD state.
That discards work. Do not type it casually.
The habit is:
inspect state
↓
identify what will be lost
↓
choose recovery action
not:
panic
↓
copy random command from the internet
Local history and remote history are separate layers
After a local commit:
your repository has the commit
remote may not
After a successful push:
remote receives the commit
That is why a commit can exist locally while GitHub does not show it yet.
And git pull is not "download my files." It coordinates changes from a configured remote into your local repository according to Git's rules.
The details become deeper later. For now, keep the layers separate in your head.
Reconstruct your own project timeline
Use the history from Lesson 4.
Create a short record:
commit 1:
what changed:
why it was separate:
commit 2:
what changed:
what test/evidence existed first:
bug-fix commit:
what failed:
what diff repaired it:
current git status:
what that status proves:
Then pick one commit and inspect it with git show.
If your explanation of the project disagrees with the diff, trust the diff and fix your explanation.
Git is very good at ruining a confident but unsupported memory of what you "definitely changed." That is one of its best features.
Reader workbench
Change Python behavior; inspect Git in the real workspace
This is the Unit's one-file practice surface. Read the code, predict one result, run it, then change a value, input, condition, or boundary and explain why the evidence changed. Multi-file projects, Git, terminals, packages, and live services still belong in the full development workspace.
Run the code to see output.
This runner executes Python only. Use the Unit's controlled terminal simulation or full workspace for git status, diff, add, commit, log, push, and recovery evidence.