8.8 KiB
Vendored
Note Revisions
Track and restore previous versions of your notes with Trilium's comprehensive revision system.
Prerequisites
- Basic understanding of note types and content
- Familiarity with note protection (for encrypted revisions)
- Understanding of database storage implications
Overview
The revision system automatically creates snapshots of note content at specific intervals, enabling version history tracking, content recovery, and change auditing. Each revision captures the complete state of a note including content, title, and metadata at a specific point in time.
How Revisions Work
Automatic Revision Creation
Revisions are created automatically when:
- Content Changes: Significant modifications to note content
- Time Intervals: Periodic snapshots based on configured intervals
- Manual Triggers: Explicit revision creation via API or UI
Revision Components
Each revision stores:
- Content: Complete note content at revision time
- Title: Note title when revision was created
- Metadata: Type, MIME type, protection status
- Timestamps: Creation and last edit dates
- Blob Reference: Efficient storage of binary content
Storage Architecture
-- Revision structure
CREATE TABLE revisions (
revisionId TEXT PRIMARY KEY,
noteId TEXT NOT NULL,
type TEXT NOT NULL,
mime TEXT NOT NULL,
title TEXT NOT NULL,
blobId TEXT,
dateLastEdited TEXT NOT NULL,
utcDateLastEdited TEXT NOT NULL,
utcDateCreated TEXT NOT NULL,
utcDateModified TEXT NOT NULL,
isProtected INTEGER NOT NULL DEFAULT 0
);
Revision Policies
Creation Triggers
Automatic Snapshots
Default policy creates revisions:
- After 5 minutes of editing
- When switching to different note
- Before major operations (delete, move)
Content-Based Triggers
Revisions created when:
- Content size changes > 20%
- Structural changes in formatted text
- File attachments modified
Retention Policies
Default Retention
- Recent revisions (< 1 day): Keep all
- Daily revisions (1-7 days): Keep one per day
- Weekly revisions (7-30 days): Keep one per week
- Monthly revisions (> 30 days): Keep one per month
Custom Policies
Configure via attributes:
// Keep all revisions
#revisionRetention=all
// Keep revisions for 90 days
#revisionRetention=90d
// Disable revisions
#disableRevisions
Working with Revisions
Viewing Revision History
Access revision history through:
- Note menu → "Revisions"
- Keyboard shortcut:
Alt+R - API:
note.getRevisions()
Comparing Revisions
View differences between versions:
const revisions = note.getRevisions();
const current = note.getContent();
const previous = revisions[0].getContent();
// Generate diff
const diff = api.createDiff(previous, current);
Restoring Revisions
Manual Restoration
- Open revision history
- Select target revision
- Click "Restore this version"
- Confirm replacement
API Restoration
// Get specific revision
const revision = api.getRevision('revision_id');
// Restore content
note.setContent(revision.getContent());
note.title = revision.title;
note.save();
// Create restoration record
note.setLabel('restoredFrom', revision.revisionId);
note.setLabel('restorationDate', new Date().toISOString());
Creating Manual Snapshots
Force revision creation:
// Create immediate snapshot
api.createRevision(note.noteId, {
title: note.title,
content: note.getContent(),
reason: 'Manual snapshot before major edit'
});
Protected Revisions
Encryption Handling
Protected notes have encrypted revisions:
- Title encrypted separately from content
- Blob content encrypted with note's key
- Requires active protected session to access
Protection Synchronization
When note protection changes:
// Protect all revisions when note becomes protected
if (note.isProtected) {
for (const revision of note.getRevisions()) {
revision.protect();
}
}
Performance Considerations
Storage Impact
Size Calculations
- Text notes: ~2KB per revision (compressed)
- Code notes: ~5KB per revision (syntax metadata)
- File notes: Full file size per revision
- Image notes: Deduplicated via blob storage
Database Growth
Monitor revision storage:
-- Check revision storage size
SELECT
COUNT(*) as revision_count,
SUM(LENGTH(content)) / 1048576 as size_mb
FROM revisions;
-- Find notes with most revisions
SELECT
noteId,
COUNT(*) as revision_count
FROM revisions
GROUP BY noteId
ORDER BY revision_count DESC
LIMIT 10;
Performance Optimization
Cleanup Strategies
- Automatic Cleanup
// Configure in options
api.setOption('revisionCleanupDays', 90);
api.setOption('revisionCleanupEnabled', true);
- Manual Cleanup
// Delete old revisions
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - 90);
for (const note of api.getAllNotes()) {
const revisions = note.getRevisions();
for (const revision of revisions) {
if (revision.dateCreated < cutoffDate) {
revision.delete();
}
}
}
- Selective Retention
// Keep only milestone revisions
note.getRevisions().forEach((revision, index) => {
// Keep every 10th revision
if (index % 10 !== 0) {
revision.delete();
}
});
Advanced Features
Revision Comparison
Generate detailed comparisons:
function compareRevisions(revisionA, revisionB) {
return {
titleChanged: revisionA.title !== revisionB.title,
contentDiff: api.diffContent(
revisionA.getContent(),
revisionB.getContent()
),
sizeChange: revisionB.contentLength - revisionA.contentLength,
timeElapsed: revisionB.utcDateCreated - revisionA.utcDateCreated
};
}
Revision Analytics
Track editing patterns:
function analyzeRevisionHistory(noteId) {
const revisions = api.getNote(noteId).getRevisions();
return {
totalRevisions: revisions.length,
averageSize: revisions.reduce((sum, r) => sum + r.contentLength, 0) / revisions.length,
editFrequency: calculateEditFrequency(revisions),
majorChanges: findMajorChanges(revisions)
};
}
Batch Operations
Process multiple revisions:
// Export all revisions for backup
async function exportRevisionHistory(noteId, outputDir) {
const note = api.getNote(noteId);
const revisions = note.getRevisions();
for (const revision of revisions) {
const filename = `${noteId}_${revision.revisionId}_${revision.dateCreated}.json`;
const data = {
revisionId: revision.revisionId,
title: revision.title,
content: revision.getContent(),
metadata: revision.getMetadata()
};
await fs.writeFile(`${outputDir}/${filename}`, JSON.stringify(data));
}
}
Troubleshooting
Revisions Not Created
Symptom: No revisions appearing for edited notes.
Solutions:
- Check if
#disableRevisionsattribute is set - Verify revision creation interval in options
- Ensure sufficient disk space for storage
- Check database write permissions
Cannot Access Revision Content
Symptom: Revision list visible but content unavailable.
Solutions:
- For protected notes, unlock protected session
- Verify blob storage integrity
- Check database consistency
- Rebuild revision index if corrupted
Excessive Storage Usage
Symptom: Database size growing rapidly due to revisions.
Solutions:
- Implement aggressive cleanup policy
- Exclude binary notes from revision tracking
- Use compression for text content
- Archive old revisions externally
Revision Restoration Fails
Symptom: Cannot restore previous version of note.
Solutions:
- Verify note isn't read-only
- Check for conflicting sync operations
- Ensure revision content isn't corrupted
- Try restoration via direct database update
Best Practices
-
Configure Appropriate Policies
- Set retention based on note importance
- Disable revisions for temporary notes
- Use manual snapshots for milestones
-
Monitor Storage Usage
- Regular cleanup of old revisions
- Archive important revisions externally
- Monitor database growth trends
-
Leverage for Workflows
- Create snapshots before major edits
- Use revisions for collaborative editing
- Track changes for audit purposes
-
Optimize Performance
- Limit revision creation frequency
- Exclude large binary files
- Implement tiered retention policies
-
Backup Considerations
- Include revisions in backup strategy
- Export critical revision history
- Test restoration procedures