Three places, not one
When you edit a file, git is looking at three versions of your project at once.
The working tree is the folder you can see. The staging area (git also calls it the index) is a draft of the next save point. The repository is the chain of commits already made.
git add copies a change from the working tree into the draft. git commit turns the draft into a permanent commit. The first git lesson had you run git add -A and skip the middle step, which is fine until the day the folder holds two unrelated changes and you want to save one without the other. That day arrives quickly when an agent is doing the editing, because agents rarely make one change at a time.
A commit is a photograph, not a list of edits
This is the idea that makes the rest of git make sense. A commit does not store “line 14 changed from X to Y”. It stores a complete snapshot of every tracked file as it was at that moment, plus a pointer to the commit before it. The red and green diff you see is computed afterwards, by comparing two snapshots.
Three things follow from that.
The id (a3f9c21) is the first seven characters of a hash of the snapshot’s contents, its parent and its message. Identical content produces an identical id; change one byte anywhere and the id changes. So a commit cannot be edited. git commit --amend does not alter the last commit, it makes a new one with a new id and quietly abandons the old one.
Files that did not change between commits are stored once, not copied. A thousand commits of a project are usually only slightly larger than the project itself.
And a commit has no idea which lines you “meant”. It holds whatever was staged. The meaning lives in your choice of what to stage together.
Staging part of a change
git add src/booking.ts # stage one file
git add -p # walk through each change and say y or n
git diff # working tree versus staging
git diff --staged # staging versus the last commitgit add -p shows you each hunk of change and asks. y stages it, n skips it, s splits a large hunk into smaller ones. It takes a minute to get used to and it is the tool for the situation above: stage the fix, commit it with a message that says what is now true, and leave the reformatting for a separate decision.
Read git diff --staged before every commit. It is exactly what the commit will contain, no more and no less. git diff on its own is not: it shows what is not yet staged.
What git does and does not track
Git tracks the contents of files. It does not track folders: an empty folder is invisible to it, which is why some projects carry an empty .gitkeep file inside directories they need to exist. It does not track timestamps, and it tracks the executable bit but no other permissions.
It does not record renames. Moving a file shows up as a deletion and an addition, and git guesses afterwards, from similarity of content, that the two were one file. Rename and heavily edit a file in the same commit and the guess fails; the history of that file appears to start from nothing.
Line endings are the trap for anyone on Windows. Windows ends lines with two characters, everything else with one. Open a file in the wrong editor and every line changes, and git diff reports that you rewrote a 400-line file when you touched one line. A committed .gitattributes containing * text=auto tells git to normalise, and it is worth adding on day one because the fix is harder after the fact.
Large files live forever
A 40 MB screen recording committed once stays in the history permanently. Every clone downloads it, even after you delete the file, because the snapshot that contained it still exists. GitHub refuses individual files over 100 MB outright.
So .gitignore is not only for secrets. Build output (.next, dist, build), node_modules, uploaded images, exports and logs all belong in it. The test: if a file can be regenerated from other files, or was produced by a user rather than by you, it does not belong in the repository.
Reading git status
Its output has three sections, in a fixed order: changes to be committed (staged), changes not staged (edited but not yet added), and untracked files (new, never added). The line you want at the end of a session is nothing to commit, working tree clean: the folder is exactly the last commit, and tomorrow starts from a known state.
Run it before an agent starts and after it finishes. The difference between the two is the agent’s whole day, and it should match what you asked for.
Every lesson here is open. Your progress is recorded once you pass the Building with AI exam.
Check your understanding
You ask an agent to fix a date bug. The diff shows the fix in one file and formatting changes across six others. You want a save point that contains only the fix. What do you do?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Beatriz, your AI tutor
