Skip to content

feat(undo-last): single-step undo via .bak snapshot#11

Merged
Sanjays2402 merged 1 commit into
mainfrom
feat/undo-last
May 17, 2026
Merged

feat(undo-last): single-step undo via .bak snapshot#11
Sanjays2402 merged 1 commit into
mainfrom
feat/undo-last

Conversation

@Sanjays2402

Copy link
Copy Markdown
Owner

What

tsk undo-last — revert the most recent change to the task file. Single-step undo for the common "oops I just deleted/renamed the wrong thing" case.

Every Store.Save() now writes the previous on-disk contents to <path>.bak before atomically writing the new contents. tsk undo-last swaps the live file and the .bak.

Properties

  • Single-step: only one snapshot ever exists. If you need durable history, that's git's job.
  • Involutive: running undo-last twice returns to the state you had before the first undo, because the swap itself is a save.
  • Best-effort: snapshot write failures (read-only FS, transient errors) never abort a save. The user's edit always lands; only the undo capability is at risk.
  • Lazy snapshot: no .bak appears until at least one save modifies an existing file. A brand-new tsk add on an empty directory leaves no .bak behind. First-run users don't get a mysterious sidecar file.

Flags

Flag Behavior
--yes, -y skip the confirmation prompt

Without --yes, the command prints what it's about to swap and waits for y/N.

Examples

$ tsk add "important thing"
added #1: important thing

$ tsk rm 1
removed 1 task(s)

$ tsk undo-last
About to swap /Users/sanjay/.tsk.md ↔ /Users/sanjay/.tsk.md.bak.
Continue? [y/N] y
restored /Users/sanjay/.tsk.md from /Users/sanjay/.tsk.md.bak

$ tsk ls
#1  important thing

Tests

5 new tests in internal/commands/undo_last_test.go:

  • basic: add → rm → undo-last restores the task
  • involutive: undo-last twice → back to post-rm state
  • no snapshot → exits with friendly "no snapshot" error
  • declining the prompt aborts and leaves the file untouched
  • save creates .bak when the source file already exists; no .bak on first-ever save

Every Store.Save() now writes the previous on-disk contents to
"<path>.bak" before atomically writing the new contents. `tsk
undo-last` swaps the .bak and current file, restoring the most
recent prior state.

Properties
  - Single-step: only one snapshot ever exists.
  - Involutive: running undo-last twice returns to the original
    state, since the swap itself is a save.
  - Best-effort: snapshot writes never abort a Save() — read-only
    or transient FS failures fall through silently.
  - Interactive by default: prompts unless --yes is passed.

Snapshot is created lazily — no .bak appears until at least one
save modifies an existing file. First-time `tsk add` leaves no
.bak behind. This avoids spamming brand-new tsk users with a
mysterious file the moment they run anything.
@Sanjays2402 Sanjays2402 merged commit 466e1e8 into main May 17, 2026
@Sanjays2402 Sanjays2402 deleted the feat/undo-last branch May 17, 2026 04:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant