See doc/architecture.txt for a (outdated but still useful) overview of the Inkscape code.
These are notes from my attempt to understand Inkscape's undo system. Please help correct errors!
Inkscape tracks in a log changes to a document's XML. Five types of changes are tracked:
Each change is stored as an "Event". For example, a change in an attribute is stored in an instance of the Inkscape::XML::EventChgAttr class where the old value and new values of the attribute are recorded (see src/xml/event.h). Three private functions allow one to optimize the change (merge with a previous change), undo the change, or replay the change.
The log is built using calls to the LogBuilder class (src/xml/log-builder.h) which create a new instance of an event and then attempts to optimize the event (merge with previous event).
Each creation/undo/replay of an event causes the CompositeNodeObserver to notify object nodes that have registered their interest in tracking the corresponding XML node of the change to the XML node. The SPObject::invoke_build() function calls sp_repr_add_lister() which registers callbacks for each of the five change types listed above. Derived classes such as SPRect may add their own special callbacks.
Manipulation of the log is done through the Inkscape::DocumentUndo class (src/document-undo.h). The basic technique is to first make the desired changes to the XML tree and then call either Inkscape::DocumentUndo::done() or Inkcape::DocumentUndo::maybeDone(). The latter call includes a "key" that allows changes of the same type (i.e. "kern:left") to be merged.