name: "undo-recover"
description: "Use when undoing, recovering, restoring, reverting, aborting, or rescuing Git work."
maturity-level: "L4"
risk-scope: "R0-R5"
version: "2.3.0"
Undo Recover
Core Question
What is the least destructive recovery action that preserves user work while matching whether the target is unstaged, staged, committed, pushed, untracked, stashed, or in an operation state?
When To Use
Use this skill when the user asks to:
- restore or discard file changes,
- unstage changes,
- undo or amend local commits,
- revert pushed commits,
- inspect reflog or recover lost commits,
- abort merge, rebase, cherry-pick, or revert,
- clean untracked files,
- remove sensitive or confidential files from committed history,
- remove tracked but repo-excluded or local-only files from Git without deleting the working-tree file,
- recover from force-push or tag/branch mistakes,
- delete, replace, retag, or recover tags when routed from
tag-release.
When Not To Use
Do not use this skill for normal branch creation/sync, conflict resolution, commit grouping, message generation, release notes, or version edits.
Route to:
branch-workflow for normal branch switch/sync/push planning.resolve-conflicts for resolving conflicts instead of aborting.atomic-commits for organizing selected changes into commits.tag-release for normal tag creation or tag push.
Required Evidence
Before recovery action, inspect or establish:
git status --short --branch,- staged and unstaged diff summaries,
- untracked file list,
- recent log and target commit/ref,
- reflog when target or lost work is unclear,
- stash list when stash is involved,
- upstream and remote state when commits or refs may be shared,
- operation state for merge, rebase, cherry-pick, or revert,
- affected paths, refs, commits, or stash entries.
- for repo-excluded or sensitive history remediation, whether the local working-tree file must be preserved or deleted.
Operating Contract
You MAY:
- inspect status, diff, log, reflog, stash, and refs,
- create rescue branches, patches, or durable refs,
- unstage exact paths when requested,
- restore exact paths when explicitly requested and safe,
- revert pushed commits rather than rewriting shared history,
- abort operations only after explaining impact and receiving confirmation.
You MUST:
- choose the least destructive recovery path,
- classify work as staged, unstaged, untracked, committed, pushed, stashed, or operation-state,
- preserve user work unless explicit destructive confirmation is given,
- create a rescue branch, patch, or durable ref for high-risk recovery where possible,
- avoid rescue branches, patches, backup commits, or durable refs that preserve confidential blobs in Git,
- verify resulting status/log/reflog/refs.
You MUST NOT:
- run destructive reset, clean, stash drop, branch deletion, tag deletion, or history rewrite without exact confirmation,
- delete untracked files without listing them first,
- drop stash without exact stash ref confirmation,
- rewrite pushed history by default,
- delete a working-tree file when the user only asked to remove it from Git history,
- purge reflog or object recovery metadata as part of history remediation without separate exact confirmation,
- broad unstage pre-existing user-staged files without confirmation.
State / Risk Table
| State | Evidence | Risk | Default Action | Confirmation | Verification |
|---|
| Inspect recovery state | status/log/reflog | R0 | Report safe options | no | evidence summarized |
| Unstage explicit paths | cached diff and named paths | R2 | Unstage only named paths when requested | no if explicit | cached diff |
| Broad unstaging request | cached file list | R3 | Show staged file list and require confirmation | yes | cached diff/status |
| Restore unstaged named file | working diff and path | R2/R3 | Restore only named path if explicit | yes if discard | diff/status |
| Local unpushed commit | log and upstream | R2/R3 | Prefer reset preserving changes | yes for destructive reset | log/status |
| Sensitive file in local-only HEAD, keep copy | local-only evidence, target path, preservation intent | R5 | Use index-only removal then amend | yes for history rewrite; separate yes for cleanup | path absent from HEAD; file untracked |
| Pushed commit | upstream/remote evidence | R4/R5 | Prefer revert, not reset | yes | log/status |
| Abort operation | operation state | R3/R5 | Explain impact and route/confirm | yes | status after abort |
| Clean untracked files | untracked list | R5 | List files and require exact confirmation | yes + preflight | dry-run/status |
| Lost commit | reflog/log evidence | R2/R3 | Create rescue branch first | yes for reset | log branch |
| Stash drop/pop | stash list | R3/R5 | Inspect stash and conflicts first | yes | stash/status |
| Tag delete/replace/retag recovery | tag refs and SHAs | R5 | Require exact tag/ref/SHA and rescue plan | yes + preflight | local/remote refs |
| Force-push recovery | local/remote refs | R5 | Stop; require explicit plan | yes + preflight | remote/ref evidence |
Workflow
- Identify the target to undo or recover.
- Inspect status, staged/unstaged/untracked state, log, reflog, stash, refs, and operation state.
- Classify risk and whether work is local, shared, destructive, or recoverable.
- Prefer rescue/proposal before mutation.
- Present least destructive option and alternatives.
- Require exact confirmation for destructive, broad, shared, or history-rewriting actions.
- Execute narrowly.
- Verify status/log/reflog/refs.
- Report action, evidence, verification, and remaining risk.
Decision Rules
- Prefer revert for pushed commits.
- Prefer reset preserving changes for local unpushed commits when undoing the commit but keeping work.
- Prefer exact-path unstage/restore over broad index/worktree changes.
- "Remove from Git history" does not imply "delete the working-tree file."
- "Do not track this file" does not imply "delete the working-tree file" or "treat this as secret".
- "Remove from current commit/history" does not imply "purge local reflog or object recovery metadata."
- Create a rescue branch or patch before high-risk destructive recovery where possible.
- Do not create rescue branches, patches, backup commits, or durable refs that retain confidential blobs.
- Do not delete untracked files without listing them and using dry-run evidence when available.
- Do not drop stash without exact stash ref and confirmation.
- Do not use assumptions for pushed/shared state.
- If the target is unclear, inspect reflog before action.
Workflow Guardrails
Repository-Excluded File Removal
Trigger:
- The user asks to stop tracking, stop committing, ignore, or keep a local-only file out of Git, without classifying it as secret or confidential.
Default: <!-- guardrail:repo-excluded.default-index-only -->
- Preserve the working-tree file and remove it from the index only when it is already tracked.
- Prefer
.gitignore when the exclusion is project-wide policy; prefer .git/info/exclude when the exclusion is local-only and should not be committed.
Must: <!-- guardrail:repo-excluded.classify-before-secret-workflow -->
- Classify the request as repo-excluded/local-only unless the user explicitly says the content is secret, confidential, credential-like, or exposed.
- Verify tracked/index status before mutation:
git ls-files -- path and git status --short -- path. - Use index-only removal for tracked files:
git rm --cached -- path. - Add or update an ignore/exclude rule only after deciding whether the rule is project-wide or local-only.
Must not: <!-- guardrail:repo-excluded.no-working-tree-delete -->
- Use
git rm path, filesystem deletion, or editor deletion when the user only asked to stop tracking or stop committing the file.
<!-- guardrail:repo-excluded.no-secret-purge-by-default -->
- Treat repo-exclusion as permission for secret scanning, history rewrite, reflog expiration, object pruning, garbage collection, or force-push cleanup.
Requires explicit confirmation:
- Removing the path from the current index/commit when it is tracked.
- Committing a project-wide
.gitignore rule. - Any history rewrite, local file deletion, recovery metadata purge, or remote rewrite.
Verification:
- Verify the path is no longer tracked or staged as intended:
git ls-files -- path and git status --short -- path. - Verify the file remains on disk when preservation was intended.
- Verify the ignore/exclude rule with
git check-ignore -v -- path when an ignore or exclude rule was added.
Sensitive History Rewrite
Trigger:
- The user asks to remove a sensitive or confidential file from committed history.
Default: <!-- guardrail:sensitive-history.default-preserve-working-tree -->
- Preserve the working-tree file unless the user explicitly asks to delete the local copy.
- For a file introduced only in local
HEAD, default to index-only removal plus amend after exact confirmation. - Load
references/sensitive-history-redaction.md before choosing commands.
Must: <!-- guardrail:sensitive-history.scope-before-amend -->
- Verify the target commit is local-only or clearly identify remote exposure.
- Verify whether the path exists only in
HEAD, in older local commits, or in pushed/shared refs before choosing amend-only remediation. - Verify the intended disk outcome; default to preserving the working-tree file.
- Use index-only removal:
git rm --cached -- path. - Amend only after history-rewrite confirmation:
git commit --amend --no-edit.
Must not: <!-- guardrail:sensitive-history.no-working-tree-delete -->
- Use
git rm path, filesystem deletion, or editor deletion when the user only asked to remove the file from history.
<!-- guardrail:sensitive-history.no-git-object-backup -->
- Create rescue branches, patches, backup commits, stashes, bundles, format-patches, notes,
git update-ref refs, backup branches, backup tags, or other durable Git objects/refs that retain confidential blobs.
<!-- guardrail:sensitive-history.no-bundled-purge-or-remote-rewrite -->
- Run recovery cleanup, metadata purge, filter rewrite, or remote rewrite in the same operation.
- Use amend-only remediation when the path exists outside
HEAD or in pushed/shared refs.
Requires explicit confirmation:
- History rewrite.
- Deleting the local working copy.
- Remote force-push.
- Local recovery metadata purge.
- Filter rewrite or multi-commit redaction.
Verification:
- Verify the file is no longer tracked:
git ls-tree -r HEAD -- path. - Verify the file remains as an untracked working-tree file when preservation was intended:
git status --short -- path.
Trigger:
- The user asks to make an old commit/blob unrecoverable from local Git metadata.
Default: <!-- guardrail:recovery-purge.separate-r5 -->
- Treat purging reflog or object recovery metadata as a separate R5 workflow.
Must:
- Verify the sensitive path is absent from the new reachable history.
- Verify any intended working-tree copy still exists before cleanup.
- Require exact confirmation such as:
Confirm: prune local Git recovery metadata for this repository now.
Must not: <!-- guardrail:recovery-purge.no-bundle -->
- Bundle metadata cleanup with index-only removal, amend, reset, filter rewrite, or remote rewrite.
- Run
git reflog expire --expire=now --expire-unreachable=now --all, git gc --prune=now, or git prune without separate exact confirmation.
Requires explicit confirmation:
- The exact local recovery metadata purge operation and repository scope.
Verification:
- Verify status, reachable-history checks, and local object cleanup results after cleanup.
- Do not claim remote or external copies were removed.
Filter Rewrite / Multi-Commit Redaction
Trigger:
- The sensitive path exists in older local commits, multiple commits, or needs redaction beyond local
HEAD.
Default: <!-- guardrail:filter-rewrite.separate-r5 -->
- Stop and prepare a separate filter-rewrite plan; do not combine it with working-tree deletion, recovery metadata purge, or remote force update.
Must:
- Identify affected refs, commit range, target path, whether any refs are shared, and the intended preservation outcome for the working-tree file.
- Prefer a dry-run or disposable clone/worktree validation when practical before mutating the primary repository.
Must not: <!-- guardrail:filter-rewrite.no-unconfirmed-filter -->
- Run
git filter-branch or git filter-repo without separate exact confirmation for the filter rewrite operation. - Treat filter rewrite completion as permission to prune recovery metadata or force-push remote refs.
Requires explicit confirmation:
- Tool, path, affected refs/range, preservation outcome, and rollback or clone-backup plan.
Verification:
- Verify the path is absent from intended reachable refs after rewrite.
- Verify status and preservation of intended working-tree files.
Force Push / Shared History Rewrite
Trigger:
- Local history was rewritten and the user asks to update a remote/shared branch.
Default:
- Stop and require a shared-history rewrite plan.
Must:
- Inspect
git status --short --branch, git branch -vv, local-only commits, and remote-only commits.
<!-- guardrail:force-push.prefer-explicit-lease -->
- Prefer
git push --force-with-lease=<ref>:<expected-old-sha> <remote> <local-sha>:<ref> over bare git push --force-with-lease or git push --force when an explicit force update is confirmed.
Must not:
- Treat local amend/reset/filter rewrite as permission to rewrite a remote branch.
- Use
git push --force unless the user explicitly requests it and accepts the additional risk.
Requires explicit confirmation: <!-- guardrail:force-push.exact-ref-sha-refspec -->
- Remote name, branch/ref, local SHA, remote SHA, expected old remote SHA, intended refspec, intended force update, and recovery plan.
Verification:
- Verify remote ref after push and report shared-history risk.
Tag Delete / Retag / Replace
Trigger:
tag-release routes destructive tag deletion, retagging, replacement, or recovery here.
Default:
- Treat tag mutation as R5 shared-ref recovery.
Must:
- Inspect exact tag name, local tag target, remote tag target, intended replacement or deletion, and recovery plan.
Must not:
- Treat normal tag creation as permission to move or delete an existing tag.
- Run
git tag -d, git tag -f, git push origin :refs/tags/, or git push --force origin tag without exact confirmation.
Requires explicit confirmation:
- Tag name, current target SHA, intended new target or deletion, remote scope, and recovery plan.
Verification:
- Verify local and remote tag refs after mutation.
Broad Reset / Clean / Checkout Overwrite
Trigger:
- The user asks for cleanup, discard, restore all, reset hard, clean, or broad overwrite.
Default:
- Inspect first and prefer exact-path actions.
Must:
- Inspect
git status --short, git diff, and git diff --cached. - List affected paths before any discard or delete action.
Must not: <!-- guardrail:broad-discard.cleanup-not-discard -->
- Interpret cleanup as permission to discard work.
- Run
git reset --hard, git reset --merge, git reset --keep, git clean -fd, git clean -fdx, git clean -xdf, git checkout -- ., git checkout -f, git switch -f, git checkout <ref> -- ., git restore ., git restore --source=<ref> ., or git restore --staged . without exact path/ref confirmation.
Requires explicit confirmation:
- Affected paths, refs, and whether staged, unstaged, or untracked work will be discarded.
Verification:
- Verify status and targeted diffs after the action.
Allowed:
- read-only inspection of status, diff, log, reflog, stash, and refs,
- rescue branch or patch creation,
- exact-path unstage or restore when explicit and safe,
- revert for pushed commits when confirmed.
Requires explicit confirmation:
- broad unstaging,
- discard/restore changes,
- reset, clean, stash pop/drop,
- abort operation,
- branch or tag deletion/replacement,
- history rewrite or force-push recovery,
- purging reflog or object recovery metadata.
Forbidden:
- destructive broad commands without confirmation,
- remote/shared mutation without exact action-specific confirmation,
- deleting or overwriting unknown user work.
Verification
Minimum verification:
- R0: state evidence summarized.
- R2: targeted status/diff check.
- R3: status plus recovery/residual-risk note.
- R4/R5: preflight evidence, explicit confirmation, rescue/rollback where possible, post-action status/log/ref verification.
Output Contract
Final response should include:
## State
- Work category and target paths/refs/commits.
## Action
- Recovery action taken or proposed.
## Evidence
- Status, diff, log, reflog, stash, or refs inspected.
## Verification
- Resulting status/log/ref checks.
## Remaining Risk
- Unrecoverable areas, unverified remote state, or follow-up needed.
Stop / Confirmation Rules
Stop when the repository state is dirty, conflicted, diverged, missing required evidence, or ambiguous in a way that could overwrite user work, invalidate the requested scope, or require a gated action.
Requires exact confirmation for:
- destructive local mutation,
- broad unstaging,
- untracked-file deletion,
- stash drop/pop,
- operation abort that discards resolution work,
- tag/branch deletion or replacement,
- remote/shared mutation,
- history rewrite or force-push recovery.
Recovery Preflight
Before any reset, restore, clean, stash pop/drop, abort operation, branch deletion, tag deletion, broad unstaging, or history rewrite:
- List affected paths, refs, commits, or stash entries.
- Classify work as staged, unstaged, untracked, committed, pushed, stashed, or in operation state.
- Identify whether the action discards, rewrites, or preserves work.
- For repo-excluded or sensitive history rewrite, identify whether the file should remain on disk; default to preserving it.
- Create a rescue branch, patch, or durable ref where appropriate, but never preserve confidential blobs in Git.
- Require exact confirmation for destructive or broad operations.
- Verify status, log, reflog, or affected refs after the action.
Before aborting merge, rebase, cherry-pick, or revert, inspect whether conflict-resolution work exists and warn that abort may discard it.
Lazy-load References
Load:
references/recovery-recipes.md for common recovery workflows.references/sensitive-history-redaction.md when removing sensitive or confidential files from Git history; do not load it for ordinary repo-excluded/local-only file cleanup unless the user classifies the content as sensitive.references/reflog.md when lost commits or refs are involved.references/stash.md when stash behavior is involved.references/destructive-commands.md before R3-R5 destructive action.references/failure-modes.md for risky recovery states.references/verification.md for post-recovery checks.