All modulesModule 09
Act II · HowCycle step 6/911 min+70 XP

Repo & Version Control

An agent can edit dozens of files while you read one sentence. Git is what makes letting it do that a reasonable decision.

After this module you can

put a project under git, commit at the right moments, and undo anything an agent does to it

A coding agent edits faster than you can read. The question was never whether it will get something wrong. The question is what being wrong costs you — and with git the answer is one command.

Without version control, every agent run is a one-way door. You end up arguing with a machine about what it changed three prompts ago and slowly losing the version that worked. With version control, a bad run is a shrug: throw it away, write a better prompt, run again. Everything bold you are about to do — long runs, risky refactors, letting an agent near the database layer — is only sensible because you can get back.

Five words carry the whole system

Word What it is Picture it as
Repo Your project folder plus its full history, stored in a hidden .git folder. Works offline, needs no account. A binder that contains every previous version of every page
Commit One saved snapshot: the exact state of the files plus a message explaining the change. A diary entry with a photo attached
Branch A parallel line of work. Build on it, and main stays untouched until you merge. Photocopying the master document to scribble on
Remote A copy of the repo on a server — usually GitHub — that you push to and pull from. The safe deposit box, off-site
Pull request A proposal to merge one branch into another. Shows exactly which lines changed and runs checks first. Handing a draft to an editor before it goes to print

That is the vocabulary. Five commands cover most days.

bash
cd qairu-signup
git init
git status
git add .
git commit -m "chore: first working version"
git log --oneline

git status is the one you will run most. It answers “what has changed since the last snapshot, and what is about to go into the next one”. git add stages the files that go into that snapshot, git commit takes it, and git log --oneline reads the history back one line per commit.

From a folder on your laptop to an address on the internet

Create an empty repository on GitHub (no README, no licence — you already have files), copy the URL it shows you, then connect the two.

bash
git remote add origin https://github.com/YOUR-NAME/qairu-signup.git
git branch -M main
git push -u origin main

After the first push, git push on its own is enough. The other direction is git pull: it brings down commits the remote has and you do not — work you did on another laptop, or a change a teammate merged while you slept. Run it before you start, not after you have already edited the same file. Now your history exists in two places, and later modules can point a host at that URL and deploy on every push.

.gitignore is the list of things that must never leave your laptop

A .gitignore file tells git which paths to pretend it cannot see. Four lines cover a typical project:

.gitignore
.env
node_modules/
dist/
.claude/worktrees/

.env holds your API keys — keeping secrets out of the repository is the entire point of environment variables. node_modules/ is reinstallable and enormous, dist/ is generated, and .claude/worktrees/ is where Claude Code puts parallel working copies once you run two sessions at once.

Write commit messages you can still read at 2 a.m.

A commit message has one job: let a future reader — you, a teammate, or an agent in a fresh session — decide in two seconds whether this is the commit they want to undo. The conventional-commits style makes that automatic: a type, an optional scope, one line of plain description.

git log --oneline
feat(signup): store reservations in D1
fix(form): reject an empty email instead of saving it
test(form): cover the duplicate-email case
refactor(api): split the handler into two files
docs(readme): how to run the dev server
chore(deps): bump astro

Six types carry almost everything: feat, fix, docs, refactor, test, chore. Keep the first line short enough to scan in a list, and put the why in the body if it needs one. The payoff is that git log --oneline becomes a changelog you can revert line by line. Anthropic’s write-up on harnesses for long-running agents arrives at the same habit from the agent’s side: have it commit after each unit of progress with a message that describes the change, so a later session can find its way back to a state that worked.

Undo has three shapes, and only one is safe after a push

This is the part to actually memorise. Match the situation to the command.

What happened What you run
The agent changed files, nothing is committed, you want the old state git restore . for tracked files
It also created new files you do not want git clean -fd — deletes untracked files and folders
You want to park the mess without losing it git stash, then git stash pop to bring it back
The last commit is bad and you have not pushed git reset --hard HEAD~1 — the commit is deleted
The bad commit is already pushed or shared git revert HEAD — a new commit undoes it

git clean -fd deletes untracked files permanently — git never recorded them, so nothing can be restored. Ignored files survive unless you add -x, so your .env is safe. Run git clean -nd first: -n lists what would go without touching anything.

Rewinds the branch and deletes the commit. Perfect while the work is still only on your laptop. After a push it is a trap: your history and the remote’s now disagree, the next push demands --force, and forcing over a branch others have pulled is how teams lose work.

Adds a new commit that is the exact inverse of the bad one. Nothing is destroyed or rewritten, and the log honestly shows both the mistake and its undo. Safe before a push and after it. This is your default.

Revert works on any commit, not only the last: read git log --oneline, copy the short hash, run git revert a1b2c3d. If later work built on it, git stops and shows you the conflict instead of guessing.

Git, visually0/6 done

Type real git commands and watch the graph. This is the safest place in the world to break something: press reset and it is gone.

main
a1b2c3dinitial commitmain
Working directory: index.astroStaged: clean
git
Type `git status` to see where you are. `help` lists the commands.
$

Missions

  1. Check the state of the repo
  2. Stage your change and commit it
  3. Create a branch called feature and switch to it
  4. Make a commit on the feature branch
  5. Go back to main and merge feature into it
  6. The agent committed something bad. Undo the last commit without deleting history
Quick check

Your agent's last commit broke the sign-up form, and you already pushed it to GitHub. What do you run?

Checkpoints are local undo. Git is permanent undo.

Claude Code keeps its own safety net. Every prompt that starts a turn creates a checkpoint, and files are snapshotted before each edit; Esc Esc on an empty input, or /rewind, opens a menu that restores code and conversation, or just one of them. For “that last edit was wrong” it beats any git command.

It is not a replacement for git, and the checkpointing docs say so. Checkpoints keep only the 100 most recent per session and are swept about 30 days after the session last saved one. More importantly, they do not track changes made by Bash commands such as rm, mv and cp, most subagent edits, edits made outside the session, or symlinked and hard-linked files.

Commit before you press Enter

Here is the rule to leave with: git status should say “working tree clean” before you send a prompt that will touch more than one file. Then commit each unit of work that passes its own check, before starting the next one.

Two reasons, and neither is bookkeeping.

93%of permission prompts users approved anywayAnthropic, Mar 2026 ↗
17%of genuinely over-eager actions the auto-mode classifier missedAnthropic, Mar 2026 ↗

First: approval fatigue is measured, not theoretical. When almost every prompt gets a yes, clicking “allow” has stopped being a decision. And the classifier Claude Code’s auto mode uses to approve on your behalf still lets 17% of genuinely over-eager actions through. Neither layer is a wall. A commit before the run is the one guardrail that never gets tired.

Second: small commits make supervision cheap. A forty-line diff you will genuinely read. A two-thousand-line diff you will scroll and approve, which is not review — it is a signature.

Git rules for your agentClaude Code · AGENTS.md or the first message of a session
Git rules for this repo:
- Before starting a task, run `git status`. If the tree is not clean, stop and tell me.
- Work on a branch named feat/<short-name> or fix/<short-name>. Never commit directly to main.
- Commit after each unit of work that passes its check. One logical change per commit.
- Message format: type(scope): what changed.
  Types: feat, fix, docs, refactor, test, chore.
- Never run `git push --force`. Never amend a commit that is already pushed.
  Never add .env or anything listed in .gitignore.
- When the task is done, show me `git log --oneline` for this branch and `git diff --stat`
  against main, then wait for my review before opening a pull request.

One branch per task, one pull request per review

Branch before the agent starts, not after: git checkout -b feat/seat-counter. If the run goes badly you delete the branch and main never knew. If it goes well, open a pull request — yes, even alone, even on a project nobody else will see. That is where you read the diff file by file, where automated checks run, and where a fresh agent session can review code it did not write.

Simon Willison’s catalogue of agentic anti-patterns names the one that matters here: do not open a pull request containing code you have not reviewed yourself; keep them small and include the evidence that it works. Anti-patterns and his chapter on using git with coding agents are what to read after this page.

Go deeperOne agent per worktree, when you start running two at once

A worktree is a second working directory on its own branch, sharing the same repo history — so two agent sessions never overwrite each other’s files. Manually: git worktree add ../qairu-feature-a -b feature-a, plus git worktree list and git worktree remove. Claude Code wraps this as claude --worktree feature-auth, which creates .claude/worktrees/feature-auth/ on a branch named worktree-feature-auth and removes clean worktrees on exit. It is a fresh checkout, so you install dependencies again and ignored files such as .env do not come along (worktrees docs). Reach for this the first time two sessions collide, not on day one.

When the agent has gone off the railsClaude Code · before you undo anything
Stop. Do not change any more files.

1. Run `git status` and `git diff --stat` and show me the raw output.
2. For each changed file, tell me in one line whether it was part of the task
   I asked for, or something you decided to change on your own.
3. Do not commit, and do not run git checkout, git restore, git reset or git clean.
   I decide what gets thrown away.
Running project · 09QAIRU Event Sign-up

Put QAIRU Event Sign-up under git, then break it on purpose

Five moves. The first three set the repo up. The last two are the ones you will repeat for the rest of the course.

  1. In the project folder: git init. Open the .gitignore you wrote in module 8 and add dist/ and .claude/worktrees/ next to .env and node_modules/ — before anything else.
  2. git add . then git commit -m "chore: first working version". Check it: git status says clean, git log --oneline shows one line.
  3. Create an empty repo on GitHub, then git remote add origin with the URL it gives you, git branch -M main, git push -u origin main. Refresh the page — your project now has an address.
  4. The drill. Run git checkout -b feat/seat-counter, then ask your agent to add a “12 seats left” counter to the sign-up page. Let it finish, then git add . and git commit -m "feat(signup): seats-left counter".
  5. Now undo it: git revert HEAD. Reload the page — the counter is gone, and git log --oneline shows both the change and its reversal. Finish with git checkout main. Your working version was never in danger, and you have now practised the exact move you will need on a bad day.
Take it with you · cheatsheetGit + conventional commits cheat sheet

Set-up, the five daily commands, the undo table by situation, and the commit-message types — on one page you can keep open beside the terminal.