It all started with the need to reinstall my OSX. I have Time Machine backups, so I planned on making the final one before update, but there is no way to actually lock it. So a good idea is to make an image of your drive with another tool. I needed to clean the old TM backups first, so I ran:
1234567
# get the earliest ones$ tmutil listbackups | head -10
2016-10-01-000000
…
# remove them$ tmutil listbackups | xargs sudo tmutil delete
…and I missed the | head part there, which meant it’d remove all the backups. Since it’s very slow at removing them (not just rm -rf), I stopped the process at the first backup, so the rest was still there, but tmutil listbackups displayed an empty list from then on. I tried remounting the drive, running tmutil inheritbackup, tmutil associatedisk, disabling and reenabling the backup destination, selecting the backup directory by Option-clicking the TM icon — nothing worked to repopulate the list, only the new backups were visible. The official Time Machine UI displayed the same situation.
I tried searching online, but stackoverflow didn’t bring any answers, and the apple’s forums are completely unhelpful. And of course apple doesn’t provide any important details whatsoever (I hate this closeness about the OS).
Nota Bene! What’s described below is somewhat risky because I’m working on my real TM backup tree. If you need to do the same stuff, be very careful about the commands!
Extended attributes, part I
I thought that some of the information is kept in the extended attributes of the backup directories. Let’s see:
The first path is the last forgotten backup, and the second is the first known to TM backup. There is definitely some stuff there, but not very clear if there is any difference.
Much better, we now see some minor changes there, but also two properties are missing from the old backup: com.apple.backupd.PreviousSnapshotVolume{Name,UUID} — those seem important. Let’s replicate them and see if that helps. First, disconnect the disk from Time Machine, just in case. Then we need to remove the very restrictive ACL permissions (sudo alone won’t help), set the attributes, and reapply the ACL:
1234567891011121314151617181920
$ sudo tmutil removedestination "$( tmutil destinationinfo | sed -nE 's/ID +: +(.*)/\1/p')"$ cd /Volumes/backups/Backups.backupdb/mac
$ ls -led 2018-02-26-140000/Macintosh\ HD
drwxr-xr-x@ 28 root wheel 95226 Feb 07:42 2018-02-26-140000/Macintosh HD/
0: group:everyone deny add_file,delete,add_subdirectory,delete_child,writeattr,writeextattr,chown
$ sudo chmod -a\#02018-02-26-140000/Macintosh\ HD
$ xattr -p com.apple.backupd.PreviousSnapshotVolumeUUID 2018-02-26-180000/Macintosh\ HD > ../../voluuid
$ xattr -p com.apple.backupd.PreviousSnapshotVolumeName 2018-02-26-180000/Macintosh\ HD > ../../volname
$ sudo xattr -wx com.apple.backupd.PreviousSnapshotVolumeName "$( cat ../../volname )"2018-02-26-140000/Macintosh\ HD
$ sudo xattr -wx com.apple.backupd.PreviousSnapshotVolumeUUID "$( cat ../../voluuid )"2018-02-26-140000/Macintosh\ HD
$ sudo chmod +a "group:everyone deny add_file,delete,add_subdirectory,delete_child,writeattr,writeextattr,chown"2018-02-26-140000/Macintosh\ HD
$ sudo tmutil setdestination /Volumes/backups
$ tmutil listbackups
Two interesting things here: first, the visible backup has the com.apple.backup.SnapshotCompletionDate; second, its .SnapshotState is "4" whereas the invisible one’s is "16". I couldn’t find any explanation online for the .SnapshotState attribute, there is only one post about .SnapshotType however: https://d4rkw1ll0w4n6.wordpress.com/2015/02/12/timemachine-4n6/:
xattr paired with the com.apple.backupd.SnapshotType will show what type of backup it it, Monthly (1), Weekly (2), or Daily (3).
Nope, we don’t need to change it. So let’s try to replicate those two attributes, with the same basic steps:
Wow! It works, the backup was recognized and appeared in the list!
Small error
Fun fact (not so fun actually). First I set the date to … 37 40 36 34 38 00, enabled TM, went to the TM UI, and saw that the earliest backup was created on January 01, 1970! That’s weird. Let’s check:
Oh, the @ symbol doesn’t look right. How do you like that?! 37 39 + 01 is not 37 40, it is 38 30! With the fixed string the backup date is correct now!
Important points
So here you go, the necessary step to reassociate the mistakenly scheduled for deletion backup is setting the com.apple.backupd.Snapshot{State,CompletionDate} attributes on the timestamped directory. The observed result seems correct, however I don’t know if I reverted all the changes made by tmutil delete.
Setting the extended attributes com.apple.backupd.PreviousSnapshotVolume{Name,UUID} to the disk directory inside the timestamped directory is unnecessary and in fact the newest, proper TM backups don’t have them — so those must be the effects of running tmutil associatedisk or tmutil inheritbackup.
Here is a small script that helped me automate the process:
Do not just run it! It worked for me, but your case may be different. I cd /Volumes/backups/Backups.backupdb/mac/, ran sudo ~/bin/tmrestore.sh 2018-02-25-200000 and then on all the previous backups using a for loop.
Conclusion
The TM behavior observed here makes sense because if you request the removal of a set of backups, the system first marks them as unusable and then deletes them slowly. The problem of course is that there is no way to say that those later backups are in fact still complete so we can still use them.
This all happened on OSX 10.11.6.
ps. Before I manually adopted all the old backups, a very strange behavior happened: after each regular backup, the “post-backup thinning stage” removed only one, the oldest, not adopted backup, even though there was enough space on the disk, and it didn’t remove any of the hourly more recent backups.