How Claude uses git, what it can see, and how to stage and commit safely.
Claude Code integrates directly with git — it can read status, stage files, commit, and create branches. But how Claude uses git is different from how you do, and the difference matters for keeping your repo clean and recoverable.
⬡ What you'll build
Claude reads your git state the same way you would — by running git commands. What it can see:
Git state visible to Claude
git statusStaged, unstaged, and untracked files. Claude checks this before deciding what to stage.
git diffCurrent unstaged changes. Claude reads this to understand what's in progress.
git diff --stagedCurrently staged changes. Claude reads this to verify what it's about to commit.
git log --onelineRecent commit history. Claude reads this for context on what's changed recently.
git branchCurrent branch and local branches. Claude won't see remote branch state unless you run git fetch first.
What Claude cannot see without your help:
git fetch before asking Claude about remote)The permissions for git operations that work in production:
{
"permissions": {
"allow": [
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(git checkout *)",
"Bash(git branch *)",
"Bash(git stash *)",
"Bash(git fetch *)",
"Bash(git merge *)"
],
"deny": [
"Bash(git push --force*)",
"Bash(git push --force-with-lease*)",
"Bash(git reset --hard *)",
"Bash(git clean -f*)"
]
}
}The denies are the four operations that destroy history or overwrite remote state. Force push is always denied — if it's ever needed, you handle it manually.
The most important git habit when working with Claude: never let Claude run git add . or git add -A.
These commands stage everything — including files Claude modified that you didn't review, untracked config files, .env files if your .gitignore has a gap, and work-in-progress you're not ready to commit.
Add this to your CLAUDE.md critical rules:
## Critical rules
- NEVER run git add . or git add -A
Always stage files explicitly: git add specific/file.ts
Or list the files: "Stage only: lib/auth.ts and app/api/auth/route.ts"Pattern for staging with Claude:
The task is complete. Before committing, tell me:
1. Which files you modified
2. What changed in each file (one sentence)
Then stage only those files (not . or -A) and show me the staged diff
before committing.This gives you a checkpoint between Claude completing work and the commit landing.
Default Claude commit messages are too generic:
Failure Pattern — Generic commit messages
✕ Before (broken pattern)
feat: Update auth fix: Fix bug chore: Various changes update: update files
✓ After (production pattern)
feat(auth): replace getUserFromCookie with getUserFromToken in API routes fix(dashboard): resolve filter-to-stats reactivity by converting to controlled state refactor(lib): extract email validation to shared validateEmail() in utils.ts fix(build): move getLessonContent to lesson-content.ts (server-only fs import)
Lesson: Generic commit messages are useless for debugging and bisecting. The commit message is documentation — write it for the engineer who needs to understand why this change was made at 2am when something breaks.
Enforce quality in CLAUDE.md:
## Commit message rules
Format: type(scope): description
Types: feat, fix, refactor, chore, docs, perf, test
Scope: the file or module primarily affected (auth, dashboard, lib, build)
Good: feat(auth): add Google OAuth callback route
Good: fix(middleware): handle null session in JWT validation
Bad: Update auth
Bad: Fix things
Bad: Various improvements
Include the "why" in the body for non-obvious changes.Before asking Claude to commit or stage, give it the full picture:
Paste this output into your Claude session when asking it to stage and commit. Claude now knows exactly what exists, what's staged, and what needs to go in each commit.
Before every commit — regardless of Claude's confidence — run this:
# 1. See what's staged
git diff --staged
# 2. Verify TypeScript is clean
node node_modules/typescript/bin/tsc --noEmit
# 3. Check for accidental files
git status
# 4. Commit with a meaningful message
git commit -m "feat(auth): replace cookie session with JWT validation"This takes 45 seconds. It catches: files staged that shouldn't be, TypeScript errors Claude introduced, accidental .env inclusion, and unintended changes to config files.
Your git workflow is production-safe when: