# How no-mistakes Implements Force-Push Safety to Prevent Discarding Upstream Commits

> No-mistakes uses lease-guarded force-push safety to stop you from discarding unseen upstream commits and prevent data loss. Learn how it works.

- Repository: [Kun Chen/no-mistakes](https://github.com/kunchenguid/no-mistakes)
- Tags: internals
- Published: 2026-07-04

---

**no-mistakes prevents data loss by implementing a lease-guarded force-push safety mechanism that verifies the remote head has not advanced with unseen commits before allowing any history rewrite.**

The kunchenguid/no-mistakes repository treats every push as a potential data-loss event. When the CI pipeline needs to rewrite history after auto-fixes or rebases, it does not issue bare `git push --force` commands. Instead, it relies on a sophisticated force-push safety system anchored in [`internal/pipeline/steps/forcepush.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/forcepush.go) that ensures upstream commits are never discarded.

## The Core Safety Guard

The heart of the implementation lives in the `resolveForcePushDecision` function within [`internal/pipeline/steps/forcepush.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/forcepush.go). This function evaluates whether rewriting history is safe by comparing three critical pieces of state passed by callers:

- **`lastSeenSHA`** – The exact SHA observed on the remote tip during the last fetch (the lease anchor)
- **`currentSHA`** – The commit SHA the pipeline currently wants to push
- **`baseSHA`** – The original base commit the run is permitted to rewrite

Two pipeline steps invoke this guard: [`internal/pipeline/steps/push.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/push.go) handles normal post-rebase pushes, while [`internal/pipeline/steps/ci_fix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/ci_fix.go) protects pushes after CI-driven commit amends.

## The Five-Stage Verification Logic

Before permitting any force-push, `resolveForcePushDecision` executes five sequential checks as documented in [`AGENTS.md`](https://github.com/kunchenguid/no-mistakes/blob/main/AGENTS.md):

### 1. New Branch Detection

If the remote does not yet contain the branch, the push is allowed immediately without additional verification.

### 2. No-Op Fast-Forward

When `currentSHA` equals `lastSeenSHA`, the remote already points to the desired commit. The operation succeeds without network transfer.

### 3. Lease-Guarded Fast-Forward

If the live remote head still equals `lastSeenSHA` and has not diverged since the last observation, the push proceeds safely using `--force-with-lease` anchored to the known SHA.

### 4. Patch-ID Content Verification

When the remote has moved, the system runs `git rev-list --cherry-pick --right-only` to compare the remote state against `currentSHA`. Every commit present on the remote but missing from the local branch must have a matching patch-id (indicating duplicate content). Unmatched commits represent "unseen upstream work" that would be lost, triggering a `forcePushWouldDiscardError`.

### 5. Base Exclusion

Commits reachable from `baseSHA` are excluded from patch-id checks because the pipeline retains the right to rewrite its own base history during rebase operations.

## Implementation in Pipeline Steps

The safety guard integrates directly into the pipeline execution flow.

### Normal Push Operations

In [`internal/pipeline/steps/push.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/push.go), the push step invokes the guard after rebasing to ensure the rewrite does not clobber external contributions:

```go
func (s *PushStep) Run(ctx context.Context, run *db.Run) error {
    // … after a successful rebase and fetch
    lastSeenSHA := run.LastFetchedBranchTip   // remote tip observed during rebase
    currentSHA   := s.repo.HeadSHA()          // SHA we want to push
    baseSHA      := run.BaseSHA                // original base of the run

    // Ask the guard whether a force‑push is safe
    decision, err := resolveForcePushDecision(ctx, lastSeenSHA, currentSHA, baseSHA)
    if err != nil {
        return fmt.Errorf("refusing to force‑push: %w", err)
    }
    if decision == forcePushWouldDiscard {
        return fmt.Errorf("refusing to force‑push refs/heads/%s: remote head %s carries commits the pipeline never incorporated", s.branch, lastSeenSHA)
    }

    // Safe – perform the push with --force‑with‑lease using the lease SHA
    return s.repo.PushWithLease(ctx, s.branch, lastSeenSHA)
}

```

### CI Auto-Fix Scenarios

In [`internal/pipeline/steps/ci_fix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/ci_fix.go), the guard protects pushes after the CI system amends commits to inject verification results or metadata, ensuring these automated rewrites do not overwrite parallel developer work.

## Protection Against Race Conditions

A critical design detail prevents a pathological race condition fixed in issue #281: **`lastSeenSHA` never updates to the live remote tip during the push decision**. If the system fetched immediately before pushing, it could silently update `lastSeenSHA` to match a newly arrived commit, then overwrite that commit believing the remote was unchanged. By anchoring the lease to the SHA captured *before* any push attempt, the system guarantees that out-of-band commits cannot slip through the safety check.

## Summary

- **Lease-guarded verification** ensures every force-push checks against a specific, immutable remote state captured at fetch time
- **Patch-ID comparison** allows the system to distinguish between true new upstream work and duplicate commits, preventing unnecessary rebase loops
- **Explicit base exclusion** permits rewriting of the pipeline's own history while protecting external contributions
- **Dual caller integration** protects both standard rebases ([`push.go`](https://github.com/kunchenguid/no-mistakes/blob/main/push.go)) and CI auto-fixes ([`ci_fix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/ci_fix.go)) through the centralized `resolveForcePushDecision` function

## Frequently Asked Questions

### What happens when unseen upstream commits are detected?

The `resolveForcePushDecision` function returns `forcePushWouldDiscardError`, causing the caller to abort and surface a clear error message: "refusing to force-push … remote head carries commits the pipeline never incorporated". The user must then manually re-fetch, re-rebase, or override intentionally.

### How does no-mistakes differ from standard git push --force-with-lease?

Standard `--force-with-lease` only verifies the remote ref matches an expected SHA. no-mistakes adds a **patch-ID content layer** that checks whether divergent remote commits are actually duplicates of local changes, allowing safe pushes even when the remote has technically moved forward with equivalent content.

### Can I override the safety guard if I need to force-push intentionally?

The analysis indicates the system aborts with an error when the guard fails. Users encountering legitimate override scenarios would need to push manually outside the no-mistakes pipeline, as the automated steps are designed to strictly prevent any discard of unseen work.

### Which pipeline steps trigger the force-push safety check?

The guard is invoked by [`internal/pipeline/steps/push.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/push.go) for normal post-rebase pushes and [`internal/pipeline/steps/ci_fix.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/ci_fix.go) when pushing amended commits after automated CI fixes. Both forward their state to the centralized `resolveForcePushDecision` function in [`forcepush.go`](https://github.com/kunchenguid/no-mistakes/blob/main/forcepush.go).