CASE FILE#4576WARNFiled 2026-04-13

Protecting Your Git History: Windsurf and Force Push

Windsurf force-pushes to fix a commit but targets the wrong remote branch. SSG blocks the destructive rewrite before it reaches your shared origin.

Case ID
#4576
Severity
WARN
Decision
FORCE
Agent
Windsurf
Category
Git Hygiene

Correction note (2026-10-13). The per-call timings and latency figures that appeared in this article had no benchmark behind them and were removed. Sample output in this article is illustrative, not a recorded run. The only published measurement is p50 0.39 ms and p99 1.91 ms (sigmashake-bench daemon-socket run, 2026-06-10, ssg 0.29.156, n=500). Sub-2 ms evaluation is a design target.

Correction note (2026-10-13). An earlier version of the rule in this article used the operator MATCHES_REGEX, which the rule DSL does not have, so the rule did not load. The rule now uses REGEX.

Describe the task

You ask Windsurf to rebase and clean up a branch. After the rebase completes, the agent pushes back to the remote — but uses --force to overwrite the branch history and accidentally targets main instead of your feature branch:

git push origin main --force

A force-push to a shared branch rewrites everyone's history. Teammates' local branches diverge. CI artifacts pointing to rewritten commits become invalid. SSG's no-force-push-main rule blocks it immediately.

# illustrative sample output
[BLOCK] bash › git push origin main --force — rule: no-force-push-main

Give SSG context

SSG evaluates Windsurf's shell commands via the SSG MCP Server integration inside Windsurf (Cascade).

Required context

rule no-force-push-main {
  enabled true
  priority 95
  severity error
  DENY execution
  IF command CONTAINS "git push" AND command CONTAINS "--force"
  AND command CONTAINS "main"
  MESSAGE "Force push to main is blocked. Use --force-with-lease on feature branches only."
}

Optional context

Extend to protect additional protected branches:

rule no-force-push-protected {
  enabled true
  priority 95
  severity error
  DENY execution
  IF command CONTAINS "git push"
  AND command CONTAINS "--force"
  AND command REGEX "(main|master|release|production)"
  MESSAGE "Force push to a protected branch is blocked."
}

What SSG does

SSG inspects the full git command including all flags and arguments. The block fires before any network connection to the remote is opened — no packets sent, no history rewritten.

Ask the agent to use a feature branch

Force push to main was blocked. Push your changes to a feature branch instead:
  git push origin HEAD:feature/my-fix --force-with-lease

--force-with-lease is the safer alternative — it fails if the remote has diverged, preventing overwrites of others' work.

See all blocked push attempts in your audit log

Run ssg dashboard and filter by no-force-push to see every push attempt blocked across all agent sessions. This is particularly useful in team environments where multiple developers use the same agent tooling.

Combine with a git pre-push hook for defense in depth

SSG blocks at the tool-call layer. Pair it with a server-side protected branch rule in GitHub/GitLab for defense-in-depth — even if an agent somehow bypasses SSG, the remote will still reject the push.

How your rule syntax handles flag ordering

Git flag ordering is flexible — git push --force origin main and git push origin main --force both work. Using CONTAINS for each component (rather than STARTS_WITH) handles all orderings correctly.

Check the rule against your release automation

Some release scripts legitimately force-push version tags or release branches. Create an exemption rule at higher priority for those specific patterns, or move release automation to a service account with SSG configured in ALLOW mode for that specific command.

Filed by Windsurf
Engine ssg v1 · 2026-04-13
End of case file

Stop reading. Start governing.

Test a rule against any tool call right now. No install required.