Build a Doc version-comparison report
Diff two Doc revisions and summarise what changed — for contract redlines.
Published Aug 31, 2025
When Northwind sends a contract back and forth with a client, the legal team needs to know exactly what moved between the version they last reviewed and the one that just came back. Scrolling through revision history in the Docs UI is slow and error-prone — a single reworded clause is easy to miss.
This script pulls the plain text of two named revisions of a Doc and compares them line by line, reporting which lines were added and which were removed. It is the raw material for a redline summary — a fast way to spot what changed without reading the whole document twice.
What you’ll need
- A Google Doc with at least two saved revisions you want to compare.
- The Drive API enabled under Services (the
+next to Services in the Apps Script editor) — the script callsDrive.Revisions.listto find revision IDs. - The Doc’s file ID, taken from its URL.
The script
/**
* Lists the saved revisions of a Doc, newest last.
* @param {string} docId The file ID of the Doc.
* @return {Object[]} Revision metadata objects with id and modifiedTime.
*/
function listRevisions(docId) {
const res = Drive.Revisions.list(docId);
return res.revisions;
}
/**
* Exports the plain text of a single revision of a Doc.
* @param {string} docId The file ID of the Doc.
* @param {string} revisionId The revision to export.
* @return {string} The revision's text content.
*/
function exportRevision(docId, revisionId) {
// The revisions endpoint with alt=media returns the file content itself.
const url = `https://www.googleapis.com/drive/v3/files/${docId}/revisions/${revisionId}?alt=media`;
return UrlFetchApp.fetch(url, {
headers: { Authorization: `Bearer ${ScriptApp.getOAuthToken()}` },
}).getContentText();
}
/**
* Compares two revisions of a Doc and reports the lines that were
* added and removed between them.
* @param {string} docId The file ID of the Doc.
* @param {string} oldRev The earlier revision ID.
* @param {string} newRev The later revision ID.
* @return {{added: string[], removed: string[]}} The line-level diff.
*/
function diffRevisions(docId, oldRev, newRev) {
// 1. Export the text of both revisions.
const oldText = exportRevision(docId, oldRev);
const newText = exportRevision(docId, newRev);
// 2. Split each into lines for a line-by-line comparison.
const oldLines = oldText.split('\n');
const newLines = newText.split('\n');
// 3. Added lines appear in the new version but not the old; removed
// lines appear in the old but not the new.
const added = newLines.filter((l) => !oldLines.includes(l));
const removed = oldLines.filter((l) => !newLines.includes(l));
// 4. Log the result so it can be read straight from the execution log.
Logger.log(`Added (${added.length}):\n${added.join('\n')}`);
Logger.log(`Removed (${removed.length}):\n${removed.join('\n')}`);
return { added, removed };
}
How it works
listRevisionscallsDrive.Revisions.listto fetch the saved revisions of the Doc. Each revision object carries anidand amodifiedTime— use it to pick the two revision IDs you want to compare.exportRevisiondownloads the content of one revision. It hits the Drive API’s revisions endpoint withalt=media, which returns the file body itself rather than metadata, authorised by the script’s OAuth token.diffRevisionsexports the text of both the old and new revisions.- It splits each export into an array of lines.
- It computes
added— lines present in the new version but absent from the old — andremoved— lines present in the old but absent from the new. - It logs both lists with their counts and returns them as an object, ready to feed into a report or an email.
Example run
Given a contract Doc, first list its revisions to get the IDs:
listRevisions('1abcContractId');
// [{ id: '0B...AQ', modifiedTime: '2025-08-20T...' },
// { id: '0B...ZX', modifiedTime: '2025-08-29T...' }]
Then diff the two:
diffRevisions('1abcContractId', '0B...AQ', '0B...ZX');
The execution log shows what moved between them:
Added (2):
Payment is due within 14 days of invoice.
Either party may terminate with 30 days' notice.
Removed (1):
Payment is due within 30 days of invoice.
At a glance: the payment window was tightened and a termination clause was added.
Run it
This is an on-demand job — run it when a revised document comes back:
- Run
listRevisionswith your Doc ID and read the execution log to find the two revision IDs you want to compare. - Call
diffRevisionswith the Doc ID and those two IDs (oldest first). - Read the added and removed lines from the execution log.
Watch out for
- Drive only retains revisions for 30 days unless they are pinned. Compare or pin important versions before they expire.
- This is a line-level diff, not a word-level one. Reword a single phrase and the whole line shows as one removal plus one addition — fine for spotting change, less precise than a true redline.
filter/includesmatches whole lines exactly. Two paragraphs that differ only in whitespace count as different lines, and identical repeated lines can confuse the comparison.- The diff ignores line order. A clause moved unchanged to a new position will not appear as added or removed — only genuinely new or deleted text shows up.
- For very long contracts the nested
filteris O(n²). It is fine for typical documents; for huge files, build aSetof each line array first.
Related
Generate personalized study guides from notes
Reformat raw notes into structured study guides — for Northwind's internal training programme.
Updated Feb 8, 2026
Build a contract-clause assembly system
Construct Northwind agreements from a library of approved clauses — drag-drop in code.
Updated Feb 1, 2026
Translate and resolve Doc comments
Localise reviewer feedback on a shared Doc so multilingual teams can collaborate.
Updated Jan 25, 2026
Auto-archive finalized Docs to dated folders
File completed Northwind Docs by month so the active folder stays focused on in-flight work.
Updated Jan 18, 2026
Build a fillable intake form inside a Doc
Create structured intake forms with placeholder fields readers can fill — for client briefs.
Updated Jan 11, 2026