Claude Code Commits and Pushes Without Asking
Symptoms
- Claude Code chains 'git add && git commit && git push' on its own.
- It commits directly to main despite CLAUDE.md rules forbidding exactly that.
- It amends commits without warning.
- In one reported case, it force-pushed over an existing private repo, replacing the entire history with a single fresh commit.
- Instructions like 'never auto-commit' get acknowledged, then ignored across sessions.
Why it happens
Git is just Bash to the agent
Once a session or allowlist permits git commands, the model's strong training prior of finishing the task by committing and pushing overrides natural-language rules in CLAUDE.md, which are suggestions rather than enforcement (issues #48474, #58883, #40695).
Claude Code on the Web overrides your rules
The Web task-agent's system prompt has hard-coded commit and push instructions that override user CLAUDE.md (issue #56865), so local rule files cannot stop it there.
Force-push rewrites the remote branch pointer
A force push overwrites the remote branch pointer, replacing the remote's visible history even though the old commits survive as orphans for a while (issue #33402).
How to fix it
- Stop the agent, then find the pre-push SHAStop the session so it cannot push again while you recover. On any machine with an old clone of the repo, run 'git reflog' or 'git log origin/main@{1}' to find the SHA the branch pointed to before the force push.
- Restore the remote branch from that SHAPush the old state back with 'git push --force-with-lease origin <sha>:main'. The --force-with-lease flag refuses to clobber anything that changed since you looked, which matters when you are undoing a force push rather than making a new one.
- No local clone? Use GitHub's events APIRun 'gh api repos/OWNER/REPO/events' to find the dangling head SHA of the old branch, then create a branch from it: 'gh api repos/OWNER/REPO/git/refs -f ref=refs/heads/restore -f sha=<sha>'. GitHub support can also recover recently orphaned commits if the events feed no longer shows them.
- Undo unwanted amends or resets locallyRun 'git reflog' to find the SHA from before the amend or reset, then 'git reset --hard <sha-before>' to return to it.
- Enforce with deny rules, not CLAUDE.md proseAdd deny rules in .claude/settings.json: "deny": ["Bash(git push:*)", "Bash(git commit:*)"]. That makes commits and pushes require an explicit human step. Natural-language rules in CLAUDE.md alone are demonstrably not reliable (issues #48474, #58883).
- Protect the remoteTurn on GitHub branch protection: protect main, block force pushes, and require pull requests. When running the agent unattended, give it a scoped token or deploy key without push access to protected branches.
How to prevent it
- Keep deny rules for git push and git commit in .claude/settings.json on every project the agent works in.
- Enable branch protection with force pushes blocked on every repo an agent can reach.
- Use scoped tokens or deploy keys without push access to protected branches for unattended runs.
- Allowlist git commands narrowly; once git is permitted, the model's commit-and-push training prior takes over.
Tools that actually fix this
Recommended because they address the failure mode above, not because of the payout. Some are affiliate links; see how we choose.
Automated, scheduled backups of your database and storage so the AI's next confident refactor is survivable. Set it once and stop trusting an agent with your only copy.
Try SimpleBackups →Backup and recovery for your Git repositories, so a force-push or an agent's cleanup does not take your history with it. Free for open-source projects.
Try GitProtect →Frequently asked questions
Why does Claude Code ignore my rule to never auto-commit?
Because CLAUDE.md rules are natural-language suggestions, not enforcement. Once a session or allowlist permits git commands, the model's strong training prior of finishing the task by committing and pushing overrides the prose, documented across issues #48474, #58883, and #40695. Deny rules in .claude/settings.json are enforced by the tool itself, which is why they work when CLAUDE.md does not.
Can I recover my repo after Claude Code force-pushed over it?
Usually, yes. A force push overwrites the remote branch pointer, but the old commits are orphaned, not instantly destroyed. Recover the pre-push SHA from any old clone's reflog or from GitHub's events API, then push it back with --force-with-lease; GitHub support can also restore recently orphaned commits.
Does Claude Code on the Web also commit and push without asking?
Yes, and for a different reason. Claude Code on the Web's task-agent system prompt has hard-coded commit and push instructions that override user CLAUDE.md, tracked as issue #56865. Your local rule files cannot fix that; branch protection and scoped credentials on the repo side can.
What deny rules stop Claude Code from pushing to git?
Add "deny": ["Bash(git push:*)", "Bash(git commit:*)"] to the permissions in .claude/settings.json. With those in place the agent can still prepare changes, but committing and pushing require you, which turns an irreversible surprise into a review step.
Sources
- GitHub: anthropics/claude-code issue #33402
- GitHub: anthropics/claude-code issue #48474
- GitHub: anthropics/claude-code issue #58883
- GitHub: anthropics/claude-code issue #56865
- GitHub: anthropics/claude-code issue #30475
Related errors
Cursor's Worktree Cleanup Force-Deleted My Git Branch
Claude Code Deleted My Home Directory (the rm -rf Incident)
Cursor Agent Deleted My Files (Wiped Uncommitted Work)
Accidentally committed an API key to GitHub
The Vibe Oops briefing
One email when something ships to production that should not have. New incidents, new error guides, no filler.