From 0ed95739b1de1cbb365fe717b8a146bb94444c9c Mon Sep 17 00:00:00 2001 From: Mark Stosberg Date: Tue, 3 Mar 2026 22:00:00 -0500 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Make=20find-replace=20safer=20by=20?= =?UTF-8?q?default=20by=20enabling=20post=20revisions=20for=20changes=20by?= =?UTF-8?q?=20defaults.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes https://github.com/TryGhost/gctools/issues/697 This aligns find-replace with how the Admin UI works. A boolean is flag is available to disable this safety feature for those want to live dangerously and not generate any more DB storage through their action. This work uncovered a bug on the server side where disabling post revisions doesn't actually work. A separate bug and PR was opened to fix that part. ref https://github.com/TryGhost/ghost/issues/26677 --- README.md | 5 +++++ commands/find-replace.js | 4 ++++ prompts/find-replace.js | 6 ++++++ tasks/find-replace.js | 3 ++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e6a3e4fb..ffeddf8c 100644 --- a/README.md +++ b/README.md @@ -437,10 +437,15 @@ gctools find-replace --tag world-news --find 'Old text' - # Custom delay between API calls gctools find-replace --find 'Old text' --replace 'New text' --delayBetweenCalls 100 + +# Replace a string without creating post revisions +gctools find-replace --find 'Old text' --replace 'New text' --no-saveRevision ``` Use `-V` (`--verbose`) for detailed output showing which fields matched or were replaced in each post. +By default, `--saveRevision` is enabled, which creates a post revision for each edited post (lexical posts only). Use `--no-saveRevision` to disable this. + Available `where` fields are: * `all` diff --git a/commands/find-replace.js b/commands/find-replace.js index ba94c3da..94ad4088 100644 --- a/commands/find-replace.js +++ b/commands/find-replace.js @@ -45,6 +45,10 @@ const setup = (sywac) => { defaultValue: 50, desc: 'The delay between API calls, in ms' }); + sywac.boolean('--saveRevision', { + defaultValue: true, + desc: 'Create a post revision for each edited post (lexical posts only)' + }); }; // What to do when this command is executed diff --git a/prompts/find-replace.js b/prompts/find-replace.js index ae77b095..12051c40 100644 --- a/prompts/find-replace.js +++ b/prompts/find-replace.js @@ -101,6 +101,12 @@ const options = [ value: 'codeinjection_foot' } ] + }, + { + type: 'confirm', + name: 'saveRevision', + message: 'Create a post revision for each edited post? (lexical posts only)', + default: true } ]; diff --git a/tasks/find-replace.js b/tasks/find-replace.js index bdde0506..6dc18ea3 100644 --- a/tasks/find-replace.js +++ b/tasks/find-replace.js @@ -141,7 +141,8 @@ const getFullTaskList = (options) => { delete post.matchesByField; try { - let result = await ctx.api.posts.edit(post); + let queryParams = ctx.args.saveRevision ? {save_revision: true} : {}; + let result = await ctx.api.posts.edit(post, queryParams); ctx.updated.push(result.url); return Promise.delay(options.delayBetweenCalls).return(result); } catch (error) {