When a coding agent edits your project, you need to see what changed and keep a version you can return to. Git gives us a way to do both. We'll first explain how Git separates the files you are editing from the versions you have recorded. Then we'll use a small game to read an agent's changes, check them, and save them as a commit. We'll also restore a file after an unwanted edit.
Suppose your project works, and you ask an agent to add a feature. The agent edits several files and saves them. Those files now contain its changes.
Saving in an editor writes the current contents to disk. By itself, it does not keep a history of earlier versions. If the new feature breaks something, we need the earlier contents to compare with or return to.
Git is a version control system. That means it keeps a history of versions of a project that we choose to record.
With that history, we can compare the current files with an earlier version, read the lines that changed, and restore recorded contents. This is especially useful with an agent, because it can change many files before we have read any of them.
Let's start with the files on your computer. The project files you can open, edit, and run are called the working tree. They include the source code and other files your program needs.
When you save an edit, or the agent writes a file, the working tree changes. This is the current work, including changes you have not yet reviewed.
A commit is a recorded version of the files Git tracks. Tracked files are the files we have brought under Git's version control. Git does not automatically include every file in a folder.
Think of a commit as a snapshot of those files together. After making a commit, we can keep editing the working tree. Those edits do not change the commit we already made.
Git stores the commits in a repository, often shortened to repo. This is where Git keeps the recorded versions and their history. In everyday conversation, people also use repo to mean the project together with that history.
Each circle here represents one commit. A new commit links back to the commit it was based on, so we can follow how the project developed. The repository and the working tree are on our computer. Recording a commit does not upload it anywhere.
Before recording a commit, we choose which changes belong in it. Git calls this staging. The staging area holds the file versions prepared for the next commit.
"git add" selects a file's current contents for that prepared version. "git commit" then records the prepared version in the repository. Unchanged tracked files remain part of the snapshot too. Selecting changes does not mean that all the other files disappear.
This separation lets us save one coherent piece of work, such as a feature and its test, while leaving unfinished edits out.
The agent can write and run these commands for you. You need to understand what each command does and read its result, so you can tell whether the agent did what you intended.
In the example, each command lights up when it runs. We'll explain it there. The full syntax is in Git's documentation when you need it.
Now let's apply that to a project. This is a small game that runs in a web browser. The ship fires at the invaders, and the score increases when it hits one.
The folder on the right contains the files that make the game. Index dot HTML is the web page. Game dot J S controls movement, hits, and the score. Theme dot C S S controls the colours and appearance.
The game already works, and this project already uses Git. We want the agent to add one feature: pressing P should pause the action and the score, and pressing P again should resume them.
Before adding pause, we ask the agent to check the current game and record the work we have so far. That gives us a starting version to compare with after the agent makes its changes.
Here the agent has checked the game and staged the current work. We'll see the selection command in detail when we save the pause feature.
The agent runs "git commit" to record that prepared version. The starting game is now saved in the repository as a commit. The working files are still there for the agent to edit.
The words "Working game" are the commit message. The dash m option supplies that message to "git commit". A useful message describes the work being recorded, so a person reading the history can recognise it.
Git also gives the commit an identifier. The short form shown here refers to this exact recorded version. We'll use it in a command to compare the agent's changes with our starting point. The message is a description we choose. The identifier is how we tell Git exactly which commit we mean.
"git status" reports the state of the current work: which changes are staged, which are not staged, and which new files Git does not track yet. Here it says "working tree clean". All tracked files match the most recent commit, so we can start the pause feature from a known version.
We ask the agent to make P pause and resume the game, with the score unchanged while paused. Before anything is committed, we will look at the changes ourselves.
On the left the game is running, the invaders advance and the score climbs. On the right it is paused, and the score holds.
The agent now runs "git status" in its short form, which lists the changed and the new files, one per line. The game logic file is marked "M", for modified. The agent also wrote a test file, code that checks the game’s behaviour automatically. Its two question marks mean Git does not track it yet. Git calls such a file untracked.
We will need to inspect the new file as well as the changes to the existing code. The saved commit itself has not changed.
Status tells us which files changed. To see what changed inside a file, we read a diff. A diff is a line-by-line comparison of two versions.
For this review, the two versions are our starting commit and the files after the agent's edit. We want to judge whether the changes implement the pause behaviour we asked for.
We run this comparison ourselves. We type "git diff" with the identifier of our checkpoint, and it prints every line that differs between the files now and that commit. You can ask the agent for a diff, but read it with your own eyes, at your own terminal.
Run this from your project folder, using the identifier of your own starting commit. The identifier on the slide belongs to our example.
This is an excerpt from the game logic. A minus marks a removed line, and a plus marks an added line.
Read the two changed lines as a replacement. The old line advanced the game on every update. The new line advances it only when pause is off.
Notice the line below them, which draws the screen. It is unchanged, and that is correct. The game needs to be rendered even when paused.
The new test file is not in this diff, because git only compares the files it tracks. Open it separately.
It checks that the score advances while the game runs, and that it does not advance while paused. That matches the request.
Check that the game works and that you like the feature before accepting it. Press P and check that the game and the score stop advancing. Then press P again and check that the game resumes.
The agent now runs "node dash dash test", which runs the project's tests, including the new one.
All four pass. If something were wrong, we would ask the agent to correct it before recording the feature as finished.
The feature works, and we have reviewed its code and its test. We want those two changes recorded together, so we ask the agent to commit both.
The agent runs "git add" with the names of the game file and the new test file. This stages their current contents for the next commit. Adding the new test also brings it under Git's tracking. Nothing has been committed yet.
Staging selects the file contents at the moment "git add" runs. Suppose we edit the game file again after staging it. The working tree now has that later edit, but the staged version still has the earlier contents.
To include the later edit, we need to run "git add" again. In our example, we are ready to commit the versions we just reviewed.
The agent now runs "git commit", with the message "Add pause control". Git records the staged changes in a new snapshot, keeping the unchanged tracked files as well.
The new commit follows "Working game" in the history. Both versions remain available. Keeping the feature and its test together makes it clear what this commit added.
Some files in a project folder should stay out of its version history. Here, dist contains generated build output, which can be recreated from the sources. The .env file holds local settings that can include secrets.
The dot gitignore file lists paths that Git should leave untracked. Its contents are shown on the left. Normal "git add" operations leave those ignored files out.
Ignoring applies to files Git does not already track. Adding a tracked file's name to gitignore does not remove it from a commit or stop Git tracking it.
Suppose the next edit breaks pause. It is not committed, and we do not want to keep it.
The diff shows the condition removed, and the pause test fails again.
We ask the agent to restore the game file from the pause commit. It confirms that this will replace the current edits in that file, which is exactly what we want.
The agent now runs "git restore", with the identifier of the pause commit as its source and the game file as its target. This puts that commit's version of the one file back into the working tree.
The pause test passes again, and the working tree is clean. The commits themselves have not changed.
This restores one tracked file from a commit we made. For other recovery situations, tell the agent what must be kept, and understand the proposed command before it runs. Git cannot recover work it never saved.
We can now let the agent work from a recorded starting point, inspect its changes, and keep the reviewed feature as a commit of its own. If a later edit damages a file, we have a saved version to restore.
The agent can help with the command syntax. Our job is to understand which version is being compared or recorded, and decide whether the changes belong in the project.
See you in the next video. We'll continue learning a bit more about Git there.