# Force-Push Safety Mechanisms in no-mistakes: Preventing Data Loss During Git Operations

> Prevent data loss with no-mistakes force-push safety mechanisms. Learn how it leases remote HEAD, performs fast-path checks, and validates commits before allowing force-pushes.

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

---

**The `no-mistakes` repository prevents data loss during force-pushes by implementing a multi-layered safety system that leases the remote HEAD, performs fast-path checks, and validates that no upstream commits would be discarded using patch-ID comparison before allowing the operation.**

Accidental force-pushes that overwrite collaborative work are a persistent risk in automated CI/CD pipelines. The `no-mistakes` tool implements robust **force-push safety mechanisms** that analyze the remote state and local changes to prevent silent data loss. These protections reside in [`internal/pipeline/steps/forcepush.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/forcepush.go) and ensure that automated rewrite operations never discard unrecognized upstream commits.

## Remote-Head Lease and Fast-Path Validation

The safety workflow begins by establishing a lease on the remote state to determine if the push is safe to proceed.

### Capturing the Remote SHA

The `lsRemoteSHA` function executes `git ls-remote` to capture the current remote SHA before any push operation. This value serves as the foundation for the **remote-head lease** mechanism. If the remote has not moved since the pipeline last observed it (`lastSeenSHA`), the system grants permission to proceed because the pipeline already possesses complete knowledge of the remote history.

### Fast-Path Exit Conditions

Before performing expensive content analysis, `resolveForcePushDecision` checks two deterministic conditions:

- **New branch**: When `ls-remote` returns no SHA, the branch does not exist on the remote, so the system performs a normal push instead of a force-push.
- **Up-to-date**: If the remote SHA already matches the `newHeadSHA`, the operation exits early with no action required.

## Content-Based Safety Net

When the remote has advanced out-of-band (the remote SHA differs from `lastSeenSHA`), the system performs a deep validation to ensure no commits would be permanently lost.

### Detecting Dropped Commits with Patch-ID

The `remoteCommitsNotIncorporated` function fetches the remote tip into `FETCH_HEAD` without disturbing remote-tracking refs. It then executes:

```go
args := []string{
    "rev-list", "--cherry-pick", "--right-only",
    fmt.Sprintf("%s...%s", newHeadSHA, remoteSHA),
}
if baseSHA != "" && !git.IsZeroSHA(baseSHA) {
    // Exclude the known base history so we don’t flag our own rewrites
    args = append(args, "^"+baseSHA)
}
out, err := gitRun(args...)

```

This command identifies commits reachable from the remote that are **not** represented in the new head by **patch-ID**—meaning the actual code changes are unique and would be lost if the push proceeded.

### Excluding Legitimate Rewrites

The mechanism distinguishes between dangerous data loss and legitimate history rewrites. By appending `^`+`baseSHA` to the rev-list arguments, the system excludes commits that are ancestors of the run's base commit. This ensures that amends, autofixes, and other pipeline-generated rewrites are not flagged as data loss, while genuine upstream contributions are protected.

## Enforcement and Error Handling

If the content analysis returns any commits, the system raises a `forcePushWouldDiscardError`. This error includes the offending SHAs and explains that the push would discard upstream work, causing the pipeline to abort immediately.

```go
// Example: deciding whether a force‑push is safe
remoteSHA, err := lsRemoteSHA(gitRun, remoteURL, ref)
if err != nil { … }

decision, err := resolveForcePushDecision(
    gitRun,
    remoteURL,
    ref,
    newHeadSHA,   // the SHA we intend to push
    lastSeenSHA, // the remote SHA last observed by the pipeline
    baseSHA,     // the base commit of the run
)
if err != nil {
    // err will be *forcePushWouldDiscardError* if the push would lose data
    log.Fatalf("push refused: %v", err)
}
if decision.upToDate {
    fmt.Println("Remote already at the desired head – nothing to do.")
} else if decision.newBranch {
    fmt.Println("Branch does not exist remotely – performing a normal push.")
} else {
    fmt.Printf("Force‑push allowed (remote lease %s).\n", shortSHA(decision.remoteSHA))
}

```

## Verification Through Integration Tests

The safety guarantees are enforced through comprehensive tests in [`internal/pipeline/steps/forcepush_safety_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/forcepush_safety_test.go) and [`internal/pipeline/steps/forcepush_decision_test.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/forcepush_decision_test.go):

- `TestCIStep_CommitAndPush_RefusesToClobberUnseenUpstreamCommit`: Verifies that CI autofix runs refuse to overwrite remote-only commits.
- `TestPushStep_RefusesToClobberAdvancedUpstreamBranch`: Confirms the push step blocks force-pushes when the remote has advanced.
- `TestForcePushRun_RefusesToClobberOutOfBandBranchCommit`: Validates that the combined rebase+push flow respects safety guarantees.

## Summary

- **Force-push safety mechanisms** in `no-mistakes` rely on remote-head leases to establish trust boundaries.
- Content validation uses `git rev-list --cherry-pick` to compare patch-IDs and detect commits that would be lost.
- The system distinguishes between legitimate pipeline rewrites and dangerous upstream overwrites by excluding the base commit history.
- A `forcePushWouldDiscardError` aborts the operation when data loss is detected.
- Integration tests verify protection against out-of-band branch advances and unseen upstream commits.

## Frequently Asked Questions

### What happens if the remote branch advances while the pipeline is running?

If the remote SHA no longer matches the `lastSeenSHA`, the `resolveForcePushDecision` function triggers `remoteCommitsNotIncorporated` to verify that no new remote commits would be discarded. If any are found, a `forcePushWouldDiscardError` is raised and the push aborts.

### How does no-mistakes distinguish between legitimate rewrites and data loss?

The system uses the `baseSHA` parameter to exclude the pipeline's own history from the safety check. By passing `^`+`baseSHA` to `git rev-list`, it ignores commits that are ancestors of the run's base, allowing amends and autofixes while blocking deletion of external contributions.

### Where is the core force-push logic implemented?

The primary implementation resides in [`internal/pipeline/steps/forcepush.go`](https://github.com/kunchenguid/no-mistakes/blob/main/internal/pipeline/steps/forcepush.go), which contains the `resolveForcePushDecision` function and the `remoteCommitsNotIncorporated` helper that performs the patch-ID comparison.

### How does the tool handle new branches that don't exist on the remote?

When `lsRemoteSHA` detects no remote SHA for the reference, the system classifies this as a new branch scenario and performs a normal push rather than a force-push, eliminating the risk of overwriting non-existent history.