Since I was doing something the other day which is related to this: sometimes, instead of implementing features like undo/rollback for a higher-level data structure, you can implement it at the level of the data structure's backing memory. While you can do it for a lower level, byte-oriented memory, it can be faster and simpler if the backing memory is more structured, e.g. an arena of typed nodes, where node fields provide a natural granularity for updates.
Ultimately it's not that different from how disk-based database systems tend to be page-oriented for their transaction layer but it works just as well for in-memory data structures and if the backing memory is strongly typed. I remember there was an academic paper (using Ocaml as the implementation language) that can basically be summarized as "persistent union-find = imperative union-find + persistent array a la Baker" but you can replicate that formula ad nauseam.