# Rollback & Time Machine

When production breaks, finding what to revert and when a problem started takes too long; these tools answer from your release history, for on-call engineers and anyone debugging a regression.

These tools answer questions about your release history: what to revert when production breaks, when something first appeared, what a change is likely to break, and what changed in an area. They read your local git checkout and the release checks, deploys and incidents Bumpkit has recorded.

| Feature | Flag | Commands | MCP tools |
|---------|------|----------|-----------|
| [Intelligent rollback](#intelligent-rollback) | `intelligent_rollback` | `bumpkit rollback plan`, `bumpkit rollback open` | `rollback_plan` |
| [Version history](#version-history) | On for every workspace | `bumpkit history --tree` | `release_history` with `tree` |
| [Rollback pull requests from an incident or a release](#roll-back-an-incident-or-a-release) | `close_the_loop` | `bumpkit rollback open`, `bumpkit loop` | `rollback_pr` |
| [Roll back to a version](#roll-back-to-a-version) | `close_the_loop` | `bumpkit rollback open --to` | `rollback_pr` with `to` |
| [Release time machine](#release-time-machine) | `release_time_machine` | `bumpkit when` | `when_introduced` |
| [Regression predictor](#regression-predictor) | `regression_predictor` | `bumpkit predict` | `predict_regressions` |
| [History queries](#history-queries) | `history_queries` | none | `what_changed`, `has_area_regressed`, `who_changed` |

## Intelligent rollback

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `intelligent_rollback`.

When a release regresses, `bumpkit rollback plan` finds the smallest set of commits to revert, proves the revert applies, and saves the plan. A workspace owner or admin then opens it as a pull request.

### Plan a rollback

From an incident Bumpkit recorded (see [Release Health & Forensics](/docs/release-health)):

```bash
bumpkit rollback plan --incident 3f2c9a1e-8b7d-4c2a-9e1f-6a5b4c3d2e1f
```

Or from a stack trace and a release range:

```bash
bumpkit rollback plan --base v1.4.0 --head v1.5.0 --error "$(cat trace.txt)"
```

| Flag | Default | Meaning |
|------|---------|---------|
| `--incident` | none | An incident Bumpkit recorded; its stack trace and suspect release are used |
| `--error` | none | The error message and stack trace |
| `--file` | none | A file in the failure (repeatable) |
| `--base` | The incident's suspect release, else the tag before `--head` | The last good release |
| `--head` | The incident's suspect release, else `HEAD` | The regressed release |
| `--commit` | none | A commit to revert regardless of evidence (repeatable) |

Nothing in your checkout changes. Bumpkit:

1. Reads up to the 200 newest non-merge commits between `--base` and `--head`.
2. Scores each commit by evidence it caused the failure:

| Evidence | Points |
|----------|--------|
| `git blame` says the commit last changed a line in the stack trace | 6 |
| The commit changed a file in the stack trace | 3 |
| Its change reaches a file in the stack trace through the code graph | 2 |
| Bumpkit proved a finding in a file it changed when the release was checked | 2 |
| Its change reaches the area where the failure is | 1 |

   A score of 6 or more is high likelihood, 3 or more is medium. Call-path reach is checked for up to 12 commits.
3. Picks the smallest set of commits (score 3 or more) that covers every stack frame, plus any `--commit` you named.
4. Adds later commits that depend on them: commits that use a symbol the reverted commit added, and commits that change the same file and would conflict. A plan reverts at most 20 commits.
5. Dry-runs `git revert --no-commit` in a temporary worktree, growing the set up to three times if it conflicts.

The plan lists the ranked suspects with evidence, the commits to revert (`revert`), the `dependents` and why each was added, whether the revert is `feasible`, any `conflicts`, the changed `files`, and the equivalent `git revert` command. Plans that revert at least one commit are saved and get an ID; saving writes `rollback.propose` to the audit log.

### Open the revert pull request

```bash
bumpkit rollback open 7b1e0c42-9a4f-4d1c-8e3b-2f6a5d4c3b2a --branch main
```

`bumpkit rollback open` re-runs the revert in a temporary worktree and, if it still applies cleanly, sends the reverted files to Bumpkit, which opens the pull request through the [Bumpkit GitHub App](/docs/#install-the-github-app) on a `bumpkit/rollback-…` branch. `--branch` defaults to the origin's default branch; `--yes` skips the confirmation prompt.

- Only a workspace owner or admin can approve. Anyone else gets `403`.
- The GitHub App must be installed on the repository and belong to your workspace. Without it, you get `409 GITHUB_APP_REQUIRED` with the `git revert` command to run by hand. If the App on the repository belongs to another workspace, you get `403 FORBIDDEN`.
- The App installation needs **Contents: write** and **Pull requests: write** to create the branch, reverted commits, and pull request. This also applies to backport and fix PRs. An installation without those write permissions returns `409 GITHUB_WRITE_REQUIRED`; its installation owner must accept them in GitHub. Release checks keep working without them.
- A plan opens once. The approval is written to the audit log as `rollback.open`, with the approver and the pull request URL.
- A revert that changes more than 300 files is refused; run it by hand.

### API

| Endpoint | Purpose |
|----------|---------|
| `GET /v1/incidents/{id}` | An incident's stack frames and suspects, used to plan from an incident |
| `POST /v1/rollbacks` | Save a plan made by `bumpkit rollback plan` (`201`) |
| `GET /v1/rollbacks/{id}` | A saved plan with its `status`, `pull_request` and `approved_by` |
| `POST /v1/rollbacks/{id}/open` | Owners and admins: `{"branch": "main", "files": [...]}` opens the pull request |

Plans are computed on your machine, because the revert needs your git checkout. Agents use the `rollback_plan` MCP tool with `incident_id` or `error`, and optionally `files`, `base`, `head`, `commits` and `path` (the local repository). The tool never opens anything; it tells the user to have an owner run `bumpkit rollback open`.

### Roll back an incident or a release

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `close_the_loop`. It also needs the Bumpkit GitHub App on the repository.

With Close the loop on, `bumpkit rollback open` also takes an incident id, a check id or a release version instead of a plan id. Bumpkit then plans and reverts on its side: it fetches the repository through the GitHub App, ranks the regressed release's commits by the incident's evidence, runs `git revert` on the tip of `--branch` (default: the default branch) and opens the pull request:

```bash
bumpkit rollback open f6fb0efa-9b13-45cc-8007-bd4a2983b012 --yes
bumpkit rollback open v1.1.0 --yes
```

```text
rollback Roll back v1.1.0 for Checkout total is 10% short  acme/shop (fix_opened)
  Pull request: https://github.com/acme/shop/pull/1
  Routed to: reviewers of https://github.com/acme/shop/pull/1
  d464ec7 feat: launch 10% discount on every price
  2026-10-23 14:45  found      Regression in v1.1.0 (incident f6fb0ef)
  2026-10-23 14:45  fix_opened Opened https://github.com/acme/shop/pull/1 reverting d464ec7 onto main
```

- The branch is `bumpkit/rollback/incident-<first 8 characters of the incident id>` or `bumpkit/rollback/<release>`. With no evidence pointing at specific commits, Bumpkit reverts the whole release, up to 20 commits.
- An incident needs a suspect release, which [What broke production](/docs/release-health#what-broke-production) records when it traces the incident.
- The pull request body links the incident, the regressed release and each suspect commit with its evidence. The gate runs on it like any pull request, and a person must merge it; Bumpkit never merges anything.
- One rollback pull request per incident or release: running it again returns the open one.
- Only owners and admins can open one (`403` otherwise). Without the App you get `409 GITHUB_APP_REQUIRED`; if the App belongs to another workspace, `403`. A revert that conflicts with the branch opens nothing, and the `409` names the files and gives the `git revert` command.
- Bumpkit opens at most 30 pull requests per workspace per hour (`429` after that).

The API is `POST /v1/loop/rollbacks` with `{"incident_id": "..."}`, `{"check_id": "..."}` or `{"release": "v1.1.0", "repository": "acme/shop"}`, and an optional `branch`. Agents use the `rollback_pr` MCP tool. The dashboard's Incidents and release pages have an **Open rollback PR** button for owners and admins.

Each rollback is tracked from found to verified. It is verified when a release gate Bumpkit ran itself passes on its pull request, and a result sent by a client leaves it open. List rollbacks, back-ports and fix tasks with their history:

```bash
bumpkit loop --kind rollback --all
```

## Version history

You shipped `v1.1.0`, then `v1.2.0`, and now you need to be back on `v1.0.0`. The version history shows the whole lineage in one place, newest first: `v1.2.0` ← `v1.1.0` ← `v1.0.0`.

Open the **Version history** tab on the dashboard's **Releases** page, or follow a repository's history link from the **Checks** page. Each release shows:

- Its version, commit range, commit count and the date Bumpkit checked it
- The check verdict and the latest gate outcome
- Every environment it was deployed to, with the one live now marked (**Live in production**) and the ones it used to run in
- The incidents traced to it
- Rollback pull requests that undo it, with their status from found to verified

**Live now** at the top lists what runs in each environment. It comes from the deploys you record with `bumpkit deploy --environment production --version v1.2.0`. A redeploy counts: deploy `v1.0.0` again and production shows `v1.0.0` as live.

From the terminal:

```bash
bumpkit history --tree
```

The API is `GET /v1/history/tree?repository=acme/shop`. See the [CLI Reference](/docs/cli-checks#bumpkit-history) for the output.

### Roll back to a version

> **Beta, early access.** Flag: `close_the_loop`. It also needs the Bumpkit GitHub App on the repository.

Owners and admins get **Roll back to v1.0.0** on every older release in the version history. Or run:

```bash
bumpkit rollback open --to v1.0.0
```

```text
Roll back acme/shop to v1.0.0 on main
Reverts v1.2.0, v1.1.0: 3 commits, 3 files changed
  3c9e1f2 feat: coupons
  8d1a4b7 docs: notes
  d464ec7 feat: launch 10% discount on every price
Commits on main after v1.2.0 that no checked release shipped stay. The gate runs on the pull request and a person merges it.
Open the pull request on bumpkit/rollback/to-v1.0.0? [y/N]
```

Before anything opens, the dashboard dialog and the CLI list exactly which releases and commits get reverted. Then Bumpkit:

1. Fetches the repository through the GitHub App.
2. Finds the releases it checked after `v1.0.0` that are on `--branch` (default: the default branch), up to the newest one.
3. Reverts every non-merge commit from `v1.0.0` up to that newest checked release, newest first, on the branch tip.
4. Opens one pull request on `bumpkit/rollback/to-v1.0.0` that lists each rolled-back release and every reverted commit.

What it touches, exactly:

- Commits in checked releases after `v1.0.0` are reverted. Commits on the branch after the newest checked release, which no release shipped yet, stay.
- `v1.0.0` must be a release Bumpkit checked or a tag in the repository, and on the branch. Otherwise you get `404` or `409`.
- At most 100 commits and 300 changed files in one pull request. Over that, or when the revert conflicts with the branch, nothing opens and the `409` gives the `git revert` command to run by hand.
- One pull request per target version: asking again returns the open one.
- Same rules as every rollback: owners and admins only, at most 30 Bumpkit pull requests per workspace per hour, recorded in the audit log, tracked from found to verified, and Bumpkit never merges it.

The API is `POST /v1/loop/rollbacks` with `{"to": "v1.0.0", "repository": "acme/shop"}` and an optional `branch`. Add `"dry_run": true` to see the releases, commits and file count without opening anything. Agents use the `rollback_pr` MCP tool with `to` and `dry_run`.

The pull request only changes code. To put `v1.0.0` back in production right now, redeploy it with your usual pipeline and record it with `bumpkit deploy --version v1.0.0`; the version history then shows `v1.0.0` live again.

## Release time machine

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `release_time_machine`.

`bumpkit when` finds the first release where something appeared, the commit that introduced it, and later changes to it.

```bash
bumpkit when --symbol ParseConfig
bumpkit when --file services/auth/session.go
bumpkit when --edge 'services/api->services/db'
bumpkit when --kind secret --path services/auth
bumpkit when --text "SQL injection"
```

| Flag | Searches |
|------|----------|
| `--symbol` | A function, method or type, like `ParseConfig` or `config.ParseConfig`, in the code graph at every release tag |
| `--file` | A file in the repository |
| `--edge` | A dependency between two areas, `FROM->TO`: when one area started calling another |
| `--kind` | A finding kind, like `secret` or `breaking_api`, in every release Bumpkit checked |
| `--text` | Text in a finding's title, detail or snippet |
| `--path` | With `--kind` or `--text`, only findings under this path |

`--symbol`, `--file` and `--edge` read your checkout. `--kind` and `--text` search stored release checks through `GET /v1/when?repository=&kind=&text=&path=`. The answer has `found`, `first_release`, `introduced_by`, up to 20 `later_changes`, `evidence` and `releases_scanned`.

Agents use the `when_introduced` MCP tool with `symbol`, `file`, `edge`, `kind` or `text`, plus `under` (path filter) and `path` (local repository).

## Regression predictor

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `regression_predictor`.

Before you ship, `bumpkit predict` ranks the existing functionality a change is likely to break.

```bash
bumpkit predict
bumpkit predict --base v1.4.0 --json
```

`--base` defaults to the latest tag and `--head` to `HEAD`. The CLI maps the change's [blast radius](/docs/release-checks) on your machine, then sends the reached areas and changed files to `POST /v1/predict`. Bumpkit ranks each area by its own history: past incidents in or near its code, files that were changed before an incident, hotspots and earlier findings.

Each area says how its likelihood was found in `method`. `calibrated` means Bumpkit measured it on enough of your past releases that touched the area, and `probability` is the measured share that later caused an incident there. `heuristic` means there isn't enough history yet: you get a likelihood and the evidence, with no probability. `sample` is the number of past releases that touched the area. Agents use the `predict_regressions` MCP tool with `base`, `head` and `path`.

## History queries

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `history_queries`.

Three questions agents ask before they change code.

### What changed in an area

```bash
curl "https://bumpkit.dev/v1/history/changes?repository=acme/api&path=services/auth&since=7d" \
  -H "x-api-key: $BUMPKIT_API_KEY"
```

`since` is a date (`2026-10-01`), a number of days (`7d`) or a release Bumpkit checked (`v1.4.0`), and defaults to 30 days. The answer lists the releases that touched the path, the agents that wrote them, and a summary with the number of files and high or medium findings. MCP tool: `what_changed` (`area`, `since`, `repository`).

### Has an area regressed

```bash
curl "https://bumpkit.dev/v1/history/regressions?repository=acme/api&path=services/auth" \
  -H "x-api-key: $BUMPKIT_API_KEY"
```

Returns `regressed` and the incidents whose stack trace ran through the path, or whose likely release changed it, with how each was resolved. MCP tool: `has_area_regressed` (`area`, `repository`).

### Who changed a symbol

The `who_changed` MCP tool (`symbol`, `path`) reads your checkout: every commit that touched the symbol's lines, with author, detected agent and release, plus the checked releases that changed its file.

## Release history

`bumpkit history` lists the checked releases that changed the repository or a path. It's on for every workspace and doesn't need `history_queries`.

```bash
bumpkit history services/auth --limit 20
```

`--limit` is up to 100 (default 20); `--repository` defaults to the `origin` remote. The API is `GET /v1/history?repository=&path=&limit=` and the MCP tool is `release_history`.

To find which releases and branches contain a commit, including cherry-picks, use `bumpkit contains 3f2a9c1` or `bumpkit contains "null pointer in checkout"`.

See the [CLI Reference](/docs/cli) and [API Reference](/docs/api-reference) for every flag and field.
