Docs

Restore tracked work without moving HEAD

Create a named checkpoint before risky work, then restore its tracked-file tree without creating a commit or moving HEAD. Read the dirty-tree warning before forcing a restore.

For: a developer who wants a local return point before an agent run, refactor, or other change to tracked files

What it does, and why it helps

A checkpoint captures the current index and tracked-file changes with git stash create. RepoOps keeps the resulting commit object reachable through an annotated tag under refs/tags/repoops-checkpoint/. Capture does not move HEAD, change the current branch, alter the index or working tree, or write to the stash. If tracked files already match HEAD, the checkpoint points to the current commit.

Restore resolves the tagged commit's tree and runs git read-tree with reset and working-tree update options. That rewrites the index and tracked files to the captured tree. It does not create a commit or move HEAD. New files that were never added to git are not captured and are not removed by the tested restore path.

The pain. A long agent run can leave many tracked edits. Recovering by hand means deciding which files belong to the useful part and which belong to the failed turn.

The point of view. Take the return point before the risky work. Treat restore as a write to tracked files, not as a harmless view and not as a move through commit history.

What gets easier. Create records a checkpoint id, commit digest, optional label, creation time, and whether tracked changes existed. The list stays newest first, and each row exposes Restore and Delete.

When it helps. Use it before a risky refactor, a long local agent run, or any experiment whose tracked-file state you may want back without adding a branch commit.

Its limits. Capture is manual. New untracked files are outside the snapshot. A failed stash-create command is treated like no tracked changes and points the checkpoint at HEAD. A failed git-status command is treated like a clean tree by the restore guard. Restore rewrites tracked files and the index, and no checkpoint is created automatically before that overwrite.

Understand it in 30 seconds

30.1 s, captions on. Narration: Microsoft Zira Desktop (provisional voice; an approved narration source is pending).Transcript
Read the narration
  1. 0:00 An agent changed tracked files.
  2. 0:02 Your new untracked file sits outside the snapshot.
  3. 0:06 Create the checkpoint before the risky run, then treat restore as a write.
  4. 0:13 RepoOps keeps an annotated tag and checks git status.
  5. 0:16 Force discards tracked work only after you type the repo id.
  6. 0:23 Restore the captured tree.
  7. 0:25 Branch history and untracked files stay outside the claim.

Synthetic example. Read the guide

Where to find it

Where to find it

  • Desktop: localhost:4000, then Remediation in the sidebar, then Checkpoints under All tools, in the Checkpoints and validation group.
  • Hosted: desktop only.
  • Keyboard: ⌘ K, then type “Checkpoints”.

When to use it

Mark a return point before an agent run

Situation. Tracked files contain a useful work-in-progress state, and the next agent run may change several of them.

What you do. Enter an optional label such as before auth refactor and press Create checkpoint. Leave the run's new files untracked only if you accept that the checkpoint will not contain them.

What you see. The page reports the generated checkpoint id, and the newest row shows that id, a shortened commit digest, the label, the creation time, Restore, and Delete. The working tree remains as it was at capture time.

What it establishes. You have a named git tree for the tracked state. This does not mark agent turns, capture new untracked files, or say that the snapshot is correct.

Return tracked files to a checkpoint

Situation. Later tracked changes are not wanted, and an earlier checkpoint holds the tree you want to materialize.

What you do. If the working tree is clean, press Restore. If it is dirty, read the refusal. Capture anything you may need, then type the repository id only if you intend to force the overwrite.

What you see. When git status reports changes, a normal restore returns working tree has uncommitted changes; pass force to overwrite and leaves the files untouched. A confirmed forced restore reports the checkpoint id and commit digest it materialized.

What it establishes. Tracked files and the index match the captured tree. The branch name, HEAD, and commit count remain unchanged in the tested path. Untracked files remain outside the claim.

Before you start

Supported versions
RepoOps desktop v0.3.1, the release this guide was read against, and git available for the tracked repository.
Where it runs
Local scope. Desktop: Remediation, then Checkpoints under All tools, in the Checkpoints and validation group. The command line and local HTTP API expose the same create, list, and restore operations; the tab also exposes deletion. The hosted /team/checkpoints page, under All tools on Remediation, is a pointer to the desktop app, not a team checkpoint store.
Permissions
The local RepoOps process needs filesystem and git access to the selected repository. The local HTTP route has no feature-specific identity role. Typing the repository id for a forced browser restore is deliberate-action friction, not authentication.
Connections
A tracked local git repository with a readable HEAD. No hosted connection, provider credential, model key, or network service is needed.
Plan
No plan gate is present in the checkpoint routes or modules. The working tree and checkpoint tags stay on the local machine.

Configure it

  1. Select the repository whose tree you mean.

    The tab reads the repo query value supplied by the desktop shell. With no repository it says No repo selected. Each API request resolves the repository again and returns unknown repo when it cannot.

  2. Create before the risky change.

    Enter an optional label and press Create checkpoint. Capture is on demand. There is no per-turn schedule or automatic pre-restore capture.

  3. Inspect the tree boundary.

    A checkpoint includes staged and unstaged changes to tracked files. Add a new file to git before capture if it belongs in the return point. A file that remains untracked is not included.

  4. Use force only after preserving current work.

    Restore refuses a dirty tree by default. In the browser, a forced restore asks you to type the repository id because it discards uncommitted tracked work. The command line force path is direct and does not add that browser confirmation.

SettingWhereA sensible choiceWhy it matters
labelCheckpoints, optional label for this checkpoint; API request body; command line create optionA short description of the state you intend to recoverThe label is stored in the annotated tag message and appears in the newest-first list. Newlines are folded to spaces.
repoDesktop shell query, API query, or command line repository optionThe tracked local repository whose working tree you are changingCheckpoint refs and restore operations belong to one git repository. An unresolved repository is refused.
forceRestore request body or command line restore optionfalse unless you intend to discard current uncommitted tracked workWithout force, changes reported by git status stop restore. The module treats a failed status command as clean. With force, RepoOps runs the same tree materialization over the current tracked work.
confirmBrowser restore request body when force is trueType the selected repository id after reading the warningThe route rejects a forced browser restore unless confirm exactly matches the repository id. The module comment states that this is deliberate-action friction, not a security token.
ⓘ
To stop or undo
Cancel the typed confirmation to leave a dirty tree untouched. There is no running job to stop. To remove a saved checkpoint, press Delete and accept the confirmation; deletion drops only that tag and does not change the working tree, index, HEAD, or other checkpoints.

What you should see

Checkpoint with tracked changes

Configuration. A tracked file is staged or modified, an optional label is present, and Create checkpoint is pressed.

Expect. When git stash create returns its commit object, the route returns a generated id, that digest, and hadChanges true. The annotated tag keeps the snapshot reachable. Capture leaves the tracked edit on disk and does not add an entry to the git stash.

Verify. The new row appears first. Its label and digest match the response. Git status still reports the same tracked edit after capture.

Checkpoint on a clean tree

Configuration. Tracked files already match HEAD when Create checkpoint is pressed.

Expect. The generated checkpoint points at the current HEAD commit and reports hadChanges false. The served success message notes that the working tree already matched HEAD.

Verify. The checkpoint appears in the list with the current commit digest. No commit, branch move, stash entry, or working-tree change is added.

Restore refusal and deliberate overwrite

Configuration. A checkpoint exists, then the working tree receives a new uncommitted tracked edit.

Expect. Restore first refuses and preserves the edit. After the repository id is typed, force restores the captured tracked tree. A tracked file added after the checkpoint can be removed; an untracked file is not removed in the tested case.

Verify. Read the refusal before confirming. After restore, compare tracked files with the checkpoint and confirm that HEAD, the branch, and the commit count did not move.

Data and cost

What is captured
An annotated git tag stores JSON metadata: id, optional label, creation time, and whether tracked changes existed. The tag points to the snapshot commit from git stash create, or to HEAD when there were no tracked changes. The commit tree contains the captured tracked-file state.
Who can see it
Local users and processes with access to the repository's git object database and checkpoint tag namespace can read the snapshots. The hosted page receives no checkpoint list and states that the local working tree is never streamed to the team database.
How long it is kept
No retention window, count cap, or automatic expiry is provided. A checkpoint tag remains until Delete removes it. After tag deletion, the snapshot commit becomes unreachable and git may prune it on its own schedule.
What leaves the machine
Nothing leaves the machine. Create, list, restore, and delete invoke local git commands. The feature makes no network or model request.
What it costs
There is no model or hosted usage charge. Checkpoints use local git object storage, whose size depends on the captured tracked content. No storage estimate or cap is provided.

When the result differs

SymptomLikely causeNext action
The tab says No repo selected.The desktop shell did not supply a repository id in the page query.Open Checkpoints from the intended tracked repository. For the API, pass that repository's id in the repo query.
The list says No checkpoints yet. Create one above.The repository has no readable checkpoint tags in the RepoOps tag namespace.Enter an optional label and press Create checkpoint before the next risky change.
Restore reports checkpoint not found.The named tag does not exist, was deleted, or does not resolve to a commit.Reload the list and choose an id that is still present. A deleted checkpoint has no restore action in RepoOps.
Restore reports working tree has uncommitted changes; pass force to overwrite.Git status reports a staged or working-tree change, so the normal restore guard stopped before writing.Create a checkpoint for anything you may need. Then clean the tree, or retry in the browser and type the repository id only if discarding the current tracked work is intended.
Create says the working tree already matched HEAD, but you expected tracked changes.Git stash create returned no digest or failed. The capture module treats both cases as hadChanges false and tags HEAD.Run git status and resolve the git error before creating another checkpoint. Confirm that the new row digest is not merely HEAD when you expect edits.
Restore did not show the dirty-tree refusal you expected.Git status returned no changes or the status command failed. The current guard converts a status error to a clean result.Check git status directly before restore. If it cannot read the repository, stop and repair that error; automatic restore rollback is not provided.
A new file was absent after restoring the checkpoint.The file was never added to git before capture. New untracked files are outside the v1 snapshot.Add files that belong in the return point before creating it. Do not assume a checkpoint contains every file visible in the directory.
Disable
Not provided. Checkpoint capture is manual and has no background schedule or feature switch to disable.
Roll back
Automatic rollback of a restore is not provided. Before restoring, create a checkpoint of the current tracked state if you may need to return to it. Restore does not create that safety copy for you.
Revoke access
Not provided. This is a local git and local API feature with no checkpoint credential or shared access grant. Files and refs inherit access from the local repository and process.
Delete
Press Delete on a row and confirm, or call DELETE /api/checkpoints with the repository and checkpoint id. It removes only the named tag. The working tree, index, HEAD, and other checkpoints stay untouched; git prunes the unreachable object on its own schedule.

Maintenance evidence

Feature id
checkpoint-rewind (spine leaf checkpoints)
Owner
Entire parity gap program, WS4. Guide: LDG-0717.
Supported product version
RepoOps v0.3.1
Last verified
2026-09-15, read against origin/main at 52366bb6d; labels read from the served tab source; create, restore, delete, command line, hosted pointer, zero state, and real-git tests checked in the repository.
Example fixtures
The suites create isolated temporary git repositories rather than keeping a fixture file. lib/checkpoints/capture.test.mjs covers clean and dirty capture, ids, list order, tag namespace, and deletion. lib/checkpoints/restore.test.mjs covers the dirty-tree refusal, tracked restore, unchanged HEAD and branch, tracked-file removal, and the untracked-file boundary. lib/routes/checkpoints.test.mjs exercises the whole HTTP lifecycle, repository resolution, typed confirmation, force, and delete against a real temporary repository.
Source references
lib/canonical-spine.json, lib/canonical-tabs.mjs, public/checkpoints.html, lib/checkpoints/capture.mjs, lib/checkpoints/restore.mjs, lib/routes/checkpoints.mjs, bin/commands/checkpoint.mjs, lib/zero-states.mjs, website/app/team/(home)/checkpoints/page.tsx
Documentation review
Independent review requested on the slice pull request; not yet recorded.
Video review
Narrated story rendered and published 2026-09-26 (render 16c018f8ba1b, LDG-1014) with the breadcrumb Remediation, which lists the feature under Moved here, checked against main at 7aab4cd82 with LDG-1014 part 1. Six frames, the captions and the transcript were reviewed by the authoring agent, not an independent reviewer; the audio was not listened to by a person. Narration is the provisional Windows voice until LDG-0721.

Last updated