Fossil Unversioned Workflow

The Fossil Source Code Management software has the ability to store files without recording a history of changes. By not recording the changes in a file, binary data can be safely stored in a Fossil repository. How can you use Fossil's unversioned command to take advantage of this feature? Read on for some ideas.

Delta Compression Conundrum

Fossil uses a form of delta compression when storing the changes in a file over time. While this process is great for files that contain text, binary data can cause the repository to grow in size. The article “Image Format vs Fossil Repo Size” explores this problem.

Unversioned Files

When it comes to binary data, usually only the “latest version” is needed. If this applies to your project, then adding the binary data as “unversioned” files is a great way to share and store those files. The command for adding an unversioned file is very simple: fossil unversioned add path/to/file and the file will be available in fossil as path/to/file. It is this simplicity which makes for a very flexible feature, yet also leads to confusion of how to “best” use it.

First, there is no one “best” way. You need to figure out how best to incorporate unversioned files into your project’s workflow. This article will explore three ways of using the fossil unversioned command.

fossil uv is the short-form of fossil unversioned command and will be used in the following examples.

The names of the following techniques are made-up and in no way “official”.

Verbatimly Verbose

Just use the default behavior: What you put in is exactly what you pull out. This approach is simple but will get verbose when exporting files from Fossil since the full name of the file must be used.

> fossil uv add foo/bar/data.bin

# ... sometime later ...

> fossil unversioned export foo/bar/data.bin foo/bar/data.bin

And what if the directory structure changes? The export must output to the new location or the old unversioned file must be removed and re-added at the new location. The added complexity can lead to headaches among your team over time.

Top-Level Dump

To avoid the problems of Verbatimly Verbose, all unversioned files can have the path removed so that only the filename is needed when exporting.

fossil uv add foo/bar/data.bin --as data.bin
fossil uuv export data.bin foo/bar/data.bin

This approach is useful when the unversioned files need to be accessed from Fossil's built-in Wiki or the files can be exported directly into the target directory. Scripting is also easier as the script would have the logic of where the file needs to be located when exported. Which leads to the next workflow…

Filename Encoding

Building on the Top-Level Dump, the scripting solution can be made more intelligent by encoding information into the unversioned filename. For example:

fossil uv add foo/bar/data.bin --as

To read the unversioned filename, everything to the right of the : is the filename. And everything to the left of the `:` is the category. The category can be further broken up into “foo” as the main category and “bar” as the subcategory by splitting on the ..

Using this filename encoding also allows you to use pattern searches to find all the files that belong to a category:

fossil uv list --glob ‘*’

Using placeholders like foo, bar, and data.bin may be too abstract to grasp how to benefit from this technique. A more concrete example using graphical assets would be a user interface. The main category would be “ui”. Subcategories would specify a theme: “beveled” and “flat”. Finally, the filenames would include “arrow_left.png”, “cursor.png”, and “push_button.png”. Combining all of the above, the resulting unversioned filenames would be:


What does this naming convention provide? Due to the use of delimiters it is easy to parse programmatically.

What assets are needed for the Beveled UI theme?

fossil uv list --glob 'ui.beveled:*' | cut -d: -f2

Which UI themes are in the repo?

fossil uv list --glob 'ui.*' | cut -d: -f1 | sort -u | cut -d. -f2

This concept can be extended to other types of files as well. Let's say the repo contains compiled 3rd-party libraries that are needed to build the software application. Let's also say that the category for these libraries will be 3rd_party.library. Now, imagine a script that would use the category name to figure out which files need to be placed in the appropriate directory. The command using such a script could look like:

uv_export 3rd_party.library lib_ext/

This script could be added to the build script, make or cmake, to ensure the latest 3rd Party library are in use. And this same script can also be used to update the UI graphics:

uv_export ui.beveled asset/ui/

Conclusion and Scripts

The Filename Encoding technique evolved from a team brainstorming session and has worked surprisingly well for the project. If you don’t want to write your own scripts or would like to know how to start, the following scripts are available for your use. Add an unversioned file or files to fossil with the specified category name. Export all the files in a category or categories into the specified directory. Copy/Move all the files in one category into another category. Useful for renaming categories.

Even if the Filename Encoding workflow does not work for your project, hopefully it provides ideas for you to explore.