Git
Git in Claude Code is ordinary git with somebody else at the keyboard: Claude Code runs git commands like any other command, so everything in this lesson is things you already know how to do. What changes is who types them and who reads the diff first.
The thing worth getting right is which of those two jobs is yours. Writing a commit message is a chore and it delegates well. Deciding what is in the commit does not.
Commit before you start, not after
The single habit that makes the rest of this comfortable: a clean working tree before you ask for anything ambitious.
git status
If that is not empty, git stash or commit first. With a clean tree, git diff is exactly
what this session did, and git checkout -- . throws away exactly this session. Without
one, you are trying to separate your changes from its changes by reading, which is the
thing you were trying to avoid.
Let it write the message
This is the delegation that pays for itself daily, because a commit message is a summary of a diff and summarising a diff is the thing it is best at.
Here is the one from lesson 12, which is the commit you already made:
Commit the working tree change on this branch. Write the message yourself from the
diff: a subject line under 72 characters and a short body saying what was wrong.
Do not push.
What came back:
Fix off-by-one in paginate start index
start was computed as clamped * pageSize, skipping an extra page of
rows on every call (page 1 returned rows starting at pageSize instead
of 0). Use (clamped - 1) * pageSize.
That is a better message than most people write for a one-line fix, and it took no thought at all. It is accurate because the diff was in front of it.
Give it the shape you want. “Subject under 72 characters”, “say what was wrong rather than what you changed”, “reference the issue number”. It follows formatting instructions reliably, which is not true of everything in this course.
By default Claude Code adds a
Co-Authored-By: Claude ...trailer to commits it makes, and a similar footer to pull request bodies. If your team would rather it did not, theattributionsetting takescommitandprkeys, and an empty string turns each off.
Review before you commit, not after
The useful move is to make Claude read its own work before it is in history:
Show me the diff you are about to commit and tell me anything in it I did not ask for.
It is oddly good at this, because the question is a reading task and it is not defending
the work. Formatting changes, a stray console.log, a file it touched while exploring:
these surface here rather than in a review three days later.
The second question is worth asking as a habit:
Is anything in this diff untested?
Branches
Nothing special. It runs git checkout -b when you ask.
The reason to bother, which is stronger with Claude Code than without it: a session that
goes wrong is throwaway if it is on a branch and a problem if it is on main. Lesson 16 said
to /clear a session that has gone sideways. Doing that on a branch means the code goes
with the conversation.
Two things worth pinning in .claude/settings.local.json, from lesson 18:
{
"permissions": {
"allow": ["Bash(git status)", "Bash(git diff *)", "Bash(git log *)"],
"deny": ["Bash(git push *)"]
}
}
Reading git is safe and constant. Pushing is a decision, and it is the one thing in a session that other people can see.
Pull requests
With gh installed and authenticated, Claude Code can open one:
Open a pull request against main. Title from the commit subject, body describing what
was wrong and how to verify it.
The body is the part worth delegating. It has the diff, the commit messages and the test output, and a PR description assembled from those beats one written from memory.
Two things to check before it goes up, both because a pull request is public inside your team:
- The base branch. It will pick
mainunless you say otherwise, and on a repository with adevelopconvention that is wrong every time. - What it claims. “Adds tests for the pagination edge cases” is worth checking against the diff. This is not it lying; it is a summary written before the last change landed.
Reading history
Lesson 13 used git log to understand a file. The same trick works for a change:
What changed in src/reports/index.ts between the first commit that touched it and now,
and why did it get so long?
And the more specific one, when you are about to delete something:
git blame src/util/dates.ts
Ask which commit introduced startOfDay and whether anything ever used it. History is the
cheapest way to tell load-bearing code from left-over code, and it is context nobody feeds
it unless asked.
What should you not delegate?
Rebases and history rewrites. git rebase -i is not available to it, and a rewrite you
did not perform yourself is a rewrite you cannot undo confidently.
Resolving conflicts on code you have not read. It will produce something that compiles. Whether it produces what both sides meant is a different question, and a merge conflict is precisely a place where the intent is not in the diff.
Pushing. Not because it is dangerous, but because it is the moment the work stops being yours alone. Make it a decision you take.
Your turn
You need a clean tree and something small to put in it. If you committed at the end of
lessons 12 and 14 you have the first already; check with git status and commit anything
outstanding before you start.
Then take the discovery from lesson 14: startOfDay and endOfDay in src/util/dates.ts
are exported and called by nothing.
git checkout -b remove-dead-dates
Delete both functions, then in a session:
Commit the working tree change on this branch. Write the message yourself from the
diff: a subject line under 72 characters and a short body saying why this is safe to
remove. Do not push.
Then check what landed:
git show --stat --format="" HEAD
git log -1 --format=%s | wc -c
git log -1 --format=%b
npm test
Check:
git show --statlistssrc/util/dates.tsand nothing else, the subject line is under 72 characters, the tests still report 86 passing, and the body says why it is safe rather than what changed. “Removed two functions” is a summary of the diff; “neither was called from src/ or test/, confirmed with grep” is a summary of the reasoning. You want the second one, and it is the sentence a reviewer actually needs.If
git show --statlists more than one file, you had uncommitted work from an earlier lesson and it has just gone into this commit with it. That is the whole argument for the first line of this lesson, learned the expensive way.
Then ask it, before you push anywhere: “Show me this diff and tell me anything in it I did not ask for.” On a one-line fix the answer should be “nothing”. Ask it again after a session that touched six files, and it will not be.
Recap
Clean tree before you start, so git diff means “what this session did”.
Delegate the commit message; it is a summary of a diff and it has the diff. Delegate the pull request body for the same reason. Keep the decisions: what goes in the commit, what the base branch is, and whether it gets pushed.
Make it review its own diff before committing. It finds the stray changes, because reading is what it is good at and it is not defending anything.
Work on branches, so that clearing a bad session throws the code away with it.
Next: the thing you type three times a week, written down once.