What does git push --force do? Risks, --force-with-lease, recovery
git push --force is a high-severity command AI coding agents run without human checkpoints. DestructGuard's default tier blocks the pattern at execution time and logs every approve-or-abort decision to a JSONL audit trail you can replay with IncidentScribe.
git push --force
Blast radius
Remote branch tip is overwritten with the local SHA. Any commits on the remote that aren't ancestors of the new tip are detached on the server. If no teammate has them locally, they exist only in the git provider's reflog (90-day GitHub default) or are gone entirely on self-hosted instances without reflog retention.
What does git push --force actually do?
It tells the remote to move the branch pointer to YOUR local commit, unconditionally — even when the remote has commits you don't. Git normally rejects a push that isn't a fast-forward precisely because that overwrite loses other people's work; --force removes that safety check. The overwritten commits aren't deleted instantly, but they become unreachable on the server and survive only in provider-side reflogs or teammates' local clones.
--force-with-lease: the safer default
`git push --force-with-lease` force-pushes ONLY if the remote branch is still where your last fetch saw it — if a teammate pushed in the meantime, the push is refused instead of silently destroying their commits. It costs nothing to type and removes the worst failure mode. Agents (and humans) should treat bare --force as a code smell; a blocklist rule that rewrites it to --force-with-lease catches most incidents before they happen.
Why agents reach for it
Agents reach for it after interactive rebases, squash merges, and any history-rewrite operation when `git push` rejects the divergence. The most common phrasing inside agent traces is 'history diverged, force-pushing to match local'.
Recovery options
GitHub Activity log + Events API expose the overwritten SHA for up to 90 days — recoverable via `git fetch <remote> <old-sha>:<branch>` from any clone. Self-hosted: check GitLab `audit_events`, Gitea `git/objects`, or run `git fsck --no-reflogs --lost-found` on a developer's clone made before the push.
Real-world incident
A Claude Code agent force-pushed a squash-rebased main over a teammate's unmerged hotfix during a release window, deleting the fix from origin. Recovery took 40 minutes of cross-referencing the teammate's local reflog against the GitHub event log.
Block it with DestructGuard's default tier
DestructGuard's default rules tier includes git push --force by default — the call is intercepted at the shell or process boundary before execution. Approvals are logged to JSONL with timestamp, caller, command, and decision. Pair with git pre-commit and pre-push hooks from the Pro Pack so destructive patterns are blocked at multiple points in the agent pipeline.
From guidance to an enforceable agent loop
Preflight this command before an agent executes it
Start with the one-cent Action Safety Quick Gate. Low risk can proceed, medium risk routes to full DestructGuard evidence, and high or critical risk routes to the complete workflow for ReviewQueue triage, a signed receipt, and a privacy-preserving status record. Triage never implies human approval.