Versioning, the Safety Net
Chapter 4 ended with a delete that left
nothing behind. File versioning is the
setting that changes that ending: when a file
in the folder is replaced or deleted, the
device keeps the old copy in a hidden folder
named .stversions instead of destroying
it.
Syncthing offers several versioning schemes; the one run here is the simplest, trash can — old copies filed under their original names, kept (as configured in the lab) indefinitely. The lab switches it on for the gazette folder on both devices, live, by editing the folder's configuration through the API:
$ curl -s -X PUT -H "X-API-Key: $KEY" http://127.0.0.1:8395/rest/config/folders/gazette -d @gaz-b2.json
[HTTP 200]
and reads it back to be sure:
{
"id": "gazette",
"type": "sendreceive",
"versioning": "trashcan",
"cleanoutDays": "0"
}
cleanoutDays: "0" is the lab's choice and
means never clean out automatically — worth
noticing, because the other choice, a number
of days, is how versioning stays a safety net
instead of a second, slower disk-full.
The overwrite that didn't destroy
Willow replaces the draft with the revised text. Juniper pulls the new version — and this time, the copy it replaced is still on its disk:
$ find share-b/.stversions -type f
share-b/.stversions/issue-12-draft.md
$ cat share-b/.stversions/issue-12-draft.md
# The Riverbend Gazette - Issue 12 (draft)
…
## Community orchard day
…
That is the previous generation of the draft — the one with the orchard paragraph — intact under its original name. Then willow changes the draft again, juniper pulls that too, and the archive is worth a second look:
$ find share-b/.stversions -type f
share-b/.stversions/issue-12-draft.md
Still one file — and it now holds the revised draft, the generation just replaced. In this version of Syncthing (1.27.2, as captured), the trash can keeps one archived copy per file, the latest one replaced; a third change would have filed the third generation over the second. If your habit is many small edits and you want several generations back, that is what the other schemes — staggered keeps timestamped copies on a thinning schedule — exist for; they are named here and in the criteria, and their behaviour is documented- only in this guide.
Whose copies get kept
Notice where the archive appeared: on juniper, the device whose copy was replaced by an incoming change. On willow, where the edits were actually made:
$ ls share-a/.stversions
ls: cannot access 'share-a/.stversions': No such file or directory
Nothing. Versioning, as captured here, catches what sync does to a device — a file overwritten or deleted by a change arriving from elsewhere — not what you do to your own files with your own editor. That placement is arguably the right one (your own editor and your own backups are your side of the fence), but learn it now rather than after: a file you overwrite on the only device where you edit has no Syncthing safety net at all.
The delete, retried
Same delete as chapter 4 — the events list, removed on willow — with versioning on:
$ find share-b/.stversions -type f
share-b/.stversions/issue-12-draft.md
share-b/.stversions/events-list.txt
Juniper's copy of the file was deleted from the
folder, as the mirror demands, and filed in
.stversions in the same motion. Recovery is
deliberately unmagical: it is a file, so you
copy it back. On juniper, under a new name so
the restore is visible as an act, not an
accident:
$ cp share-b/.stversions/events-list.txt share-b/events-list-restored.txt
The restored file is an ordinary new file, so it syncs to willow like one — and the hashes close the loop, against the pristine fixture the lab started from:
$ sha256sum fixtures/events-list.txt share-b/events-list-restored.txt share-a/events-list-restored.txt
acb3531ab279d3980d1d2901363923da7d45f242aceb9c94e2fa54c631c04651 fixtures/events-list.txt
acb3531ab279d3980d1d2901363923da7d45f242aceb9c94e2fa54c631c04651 share-b/events-list-restored.txt
acb3531ab279d3980d1d2901363923da7d45f242aceb9c94e2fa54c631c04651 share-a/events-list-restored.txt
The file that was deleted on one continent of the setup is back on both, byte for byte.
Check: the shape of the promise. Versioning
on a folder, one device deletes a synced file,
and the surviving device should hold
.stversions/<filename> with the old contents.
If it doesn't, the usual reason is the one this
chapter demonstrated on willow: you are looking
on the device that made the change.