I should use Git, I know, but when there’s only one of you writing code it seems overkill. Besides, Xcode manages versions automatically without having to resort to using Git or other code management systems. It just doesn’t give you easy access to the dozens of versions it saves for you. This article explains how you can access and recover old versions of Xcode source whether or not you use Git.
Many Mac apps support the macOS version system. Old versions of documents are normally accessed through the Revert To command in the File menu, and selecting the Browse All Versions… command enters its full-screen version browser, resembling the interface of the Time Machine app. Probably one of the least-used features in apps, some like Xcode seem to support it, but make it hard to access. I have yet to work out how in Xcode’s standard working window I can view previously saved versions of any file in a project.
In the many apps that support the macOS version system, each time that a document is saved, a copy is added to that volume’s version database, hidden in the .DocumentRevisions-V100 folder found at the top level on volumes with saved versions of files. That appears to consist of a database, together with copies of old versions of files.
There are some notable limitations to this system. Because these versions are saved in a database on the volume storing the original document, when you copy or move that document to another volume, the versions don’t move with it, and are lost. If you want access to the same versions from two different Macs, that’s a problem, as each time you copy it across, all the previous versions are blown away. iCloud can provide a workaround, so long as all who access that document leave it in the same folder in iCloud Drive. When you do copy it down, though, those old versions are gone. One serious consequence of this immobility of versions is that backup copies of documents saved by Time Machine or any other backup software lose their version history too.
Recognising those limitations, I put together a utility to address most of them. My free Revisionist, and its complementary DeepTools, help you access saved versions, and preserve them when copying files between volumes, even over the Internet if you wish. Revisionist will open any file type and show full details of every version of that document, including their sizes. You can preview and open them too, letting you create composites from older versions, and save every revision to compare changes in each, perhaps using BBEdit’s superb Find Differences feature.
How many versions?
The first surprising discovery when you look for saved versions in your Xcode projects (or anywhere else) is just how many there are. Revisionist has a crawler that checks each document in a folder to see how many versions of that are in the volume’s version database, and reports those numbers in detail. You’ll also be amazed at how many saved versions some files have: it can run into hundreds. That’s because Xcode saves a version each time a file is saved, which is every changed file for each build, plus all those you explicitly save.
Open one of those source files with a few saved versions using Revisionist and you can browse any of them right back to the first.
Double-click on a version to preview it, and have the option to open that version using Xcode.
Select any version and click the Save button to make an accessible copy of that version. If you want to save the whole set, click on Archive and Revisionist creates a new folder and writes a copy of every version into it as a separate file, all carefully numbered in sequence.
Revisionist can also use those archive folders to move a document complete with all its versions to a different volume, something macOS can’t. Simply copy that folder to its destination, which could be another Mac anywhere in the world, then use the UnArchive command in Revisionist’s Window menu to reconstitute the file complete with local versions in the new volume’s version database. You don’t even need to use Revisionist to do that: if all you want to do is copy a file with all its versions, DeepCopy in my DeepTools will do that with a minimum of fuss.
Unlike backups, a new version is created each time you, or Xcode, saves a file. This gives much finer granularity in the changes retained in the version database. When I’m coding at pace, the hour-long gap between Time Machine backups can miss a great deal of important detail. Whole procedures can be added and removed before the next scheduled backup; those will be lost from Time Machine, but retained in full in the version database.
There’s another benefit from restoring a document from an older version rather than a backup: using versions preserves existing versions, so you retain full access to the document history. When you restore a document from a backup, all previous versions are destroyed. If you change your mind, all you can do is restore a more recent copy from a backup, which has also lost its entire version history.
Unlike Git and other code management systems, saving changes isn’t restricted to a commit. All it takes is a save or build, and that version is retained automatically.
Whether you access them or not, saved versions accumulate and can steadily eat away at free disk space. For instance, one Swift source file currently occupying 13 KB has 88 stored versions; when archived by Revisionist, those come to a total of nearly 1 MB, showing the storage amplification that the version database can cause.
Revisionist is valuable for its ability to thin stored versions for individual files. Although there’s no global way to do that, if you wanted to strip all old versions from the files in a specific project, one quick way is to copy that folder to another volume and copy it back again. My free utility Scrub can also strip versions without having to copy anything.
It’s worth bearing in mind that the version database on each volume may be hidden from our eyes, but it’s still included in APFS snapshots. Not only will the versions of that 13 KB source code file take up space in the volume’s version database, but every change made in that database will be reflected in snapshots covering the period of change. Volume version databases can take up substantial space normally accounted for as System Data.
Versions are a powerful tool in Xcode and many other apps. They go where backups and source control management can’t, once you know how to get the most out of them.