This guide puts back what a change did: the files one change wrote, a row it deleted, or the whole database as it was at a moment you named. Every command it uses is described in History and snapshots.
A snapshot names the whole database as it is – rows, schemas, settings, and files with faults – so that it can be put back exactly:
$ reldir snapshot create before-cleanup
took snapshot before-cleanup
Name it for what you are about to do. reldir doctor takes one by itself
before every repair that rewrites rows or renames files.
Then make the change. Here a tag is deleted, and its foreign key removes it from the posts that carry it; then a title is changed:
$ reldir sql "DELETE FROM tags WHERE id = 'history'"
remove posts/p1.json (posts.tags[] -> tags of ["history"] in tags/history.json)
action | path | planned
-------+-------------------+--------
delete | tags/history.json | false
write | posts/p1.json | false
(2 rows)
committed: 2 file(s), revision #2 ([..])
$ reldir sql "UPDATE posts SET title = 'Engines of Analysis' WHERE id = 'p1'"
action | path | planned
-------+---------------+--------
write | posts/p1.json | false
(1 row)
committed: 1 file(s), revision #3 ([..])
reldir log lists revisions, newest first; --limit N shows the last few.
reldir show lists the rows a revision changed, and reldir diff shows the
values – the old one beside the new:
$ reldir show 3
action | path
---------+--------------
modified | posts/p1.json
(1 row)
revision #3 ([..]) (user, [..]): 1 row(s) changed
$ reldir diff --from 2 --to 3
change | pointer | old | new | path
--------+---------+---------+---------------------+--------------
changed | /title | Engines | Engines of Analysis | posts/p1.json
(1 row)
1 change(s)
reldir restore writes files back byte for byte as a revision recorded them.
To undo revision 3, restore what it changed from the revision before it:
$ reldir restore posts/p1.json --at 2
path | revision
--------------+------------------
posts/p1.json | #2 ([..])
(1 row)
action | path | planned
-------+---------------+--------
write | posts/p1.json | false
(1 row)
restored: 1 file(s), revision #4 ([..])
A restored file is whole: anything written to it after that revision is undone
too. To undo only some members and keep later edits to the same file, write
the old values back instead – reldir update posts p1 '{"title": "Engines"}',
or one SQL statement or script for many rows.
Without --at, each file comes from the newest revision that holds it:
$ reldir restore tags/history.json
path | revision
------------------+------------------
tags/history.json | #1 ([..])
(1 row)
action | path | planned
-------+-------------------+--------
write | tags/history.json | false
(1 row)
restored: 1 file(s), revision #5 ([..])
The delete also removed the tag from the posts that carried it, through the
foreign key’s remove action. Restoring the tag does not put those references
back; restore the posts as well – several files restore as one change:
$ reldir restore posts/p1.json --at 1
path | revision
--------------+------------------
posts/p1.json | #1 ([..])
(1 row)
action | path | planned
-------+---------------+--------
write | posts/p1.json | false
(1 row)
restored: 1 file(s), revision #6 ([..])
A restore is judged like any other change: a row that references a row no
longer there is refused with FOREIGN_KEY_VIOLATION, and restoring both in one
command brings them back together.
To return to a snapshot, restore it. Everything made since the snapshot is undone with it – every row, schema and setting becomes what the snapshot holds – so see first what the restore would change:
$ reldir sql "UPDATE users SET name = 'Ada Lovelace' WHERE id = 'ada'"
action | path | planned
-------+----------------+--------
write | users/ada.json | false
(1 row)
committed: 1 file(s), revision #7 ([..])
$ reldir snapshot restore before-cleanup --dry-run
action | path | planned
-------+----------------+--------
write | users/ada.json | true
(1 row)
dry run: 1 file(s) would change; nothing was written
$ reldir snapshot restore before-cleanup --yes
action | path | planned
-------+----------------+--------
write | users/ada.json | false
(1 row)
restored: 1 file(s), revision #8 ([..])
The restore is itself a change, recorded as a revision, so it can be undone the same way.
When you no longer need it, delete the snapshot. What only it kept is removed
from disk by the next reldir gc:
$ reldir snapshot delete before-cleanup --yes
deleted snapshot before-cleanup