auditing relations (or associations) is one of the main features of Envers. You can find a detailed description on how Envers stores and retrieves data in the documentation. For many-to-many relations, you need a join table, and Envers creates a parallel audit join table.
There's some information here:
Relations aren't handled in any special way, just the id of the related entity is written to the audit table.
When you read an entity that has some relations, a special proxy is created that (lazily) for each such field, which reads the related entity at the given revision, using the same algorithm as reading an entity at a given revision using the AuditReader.