Is it possible to delete post/page revisions from the database when a post/page is published?

11/05/12 Answer: See the plugin below by bueltge

I want to do this on a site with 5,000 posts and 125,000 comments; it's on a VPS and can handle the wp_posts table size - before I deleted all revisions, the table was 1.5 gigs - but I still want to keep the overall database size to a minimum by preventing revisions.

But, the client tells me he lost a big post due to a browser freeze, so: is it possible to delete post/page revisions from the database for each post/page when it is published?

What hook would be used? Is save_post the correct one? http://codex.wordpress.org/Plugin_API/Action_Reference/save_post

I have the autosave parameter set in wp-config.php, but according to the docs, that autosaves the post/page as it is being worked on, and overwrites each autosave.

What I want to do is have revisions accumulate for drafts - however many, depending on how many times "Save" and "Update" are used by the author - but once the draft is published, delete all revisions. There will only be revisions for the one post, but rather than try and parse the post_ID, the SQL query can run through all posts.

This is what I'm trying in functions.php, but I get a Call to a member function query() on a non-object error.

function delete_revisions_on_publish( $post_id ) {

    if ( !wp_is_post_revision( $post_id ) ) {

remove_action('save_post', 'delete_revisions_on_publish');

    "DELETE a,b,c
    FROM wp_posts a
    LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id)
    LEFT JOIN wp_postmeta c ON (a.ID = c.post_id)
    WHERE a.post_type = 'revision' "
add_action( 'save_post', 'delete_revisions_on_publish' );

3 Answers 3


I think a small plugin with the hook 'publish_posts' is enough. But I dont know about a core function to delete revisions and I use a query with WP functions. The source is untested, written only for this post.

 * Plugin Name: WPSE71248 Delete Revisions on Publish Posts
 * Plugin URI:  http://wordpress.stackexchange.com/questions/71248/
 * Description: 
 * Version:     1.0.0
 * Author:      Frank Bültge
 * Author URI:  http://bueltge.de
 * License:     GPLv3

! defined( 'ABSPATH' ) and exit;

add_action( 'publish_post', 'fb_remove_revisions' );

function fb_remove_revisions( $post_id = FALSE ) {

    $post_id = (int) $post_id;

    $revisions = '';
    // Get the revisions
    $revisions = new WP_Query( array(
        'post_status'    => 'inherit',
        'post_type'      => 'revision',
        'showposts'      => -1,
        'posts_per_page' => -1,
        'post_parent'    => $post_id
    ) );

    if ( empty( $revisions ) )
        return $post_id;

    // Remove the revisions the non-core-way
    global $wpdb;
    foreach ( $revisions->posts as $revision ) {
        $query = $wpdb->prepare(
            DELETE FROM $wpdb->posts 
            WHERE ID = %d
            AND post_parent = %d
        $wpdb->query( $query );

    return $post_id;

Alternative use the download from Gist 4017151

  • Looks good and it should work, but I get a parse error on the public function fb_remove_revisions( $post_id = FALSE ) { line. Commented Nov 4, 2012 at 2:12
  • Remove the 'public', it is from use in class. I will update the answer.
    – bueltge
    Commented Nov 4, 2012 at 22:25
  • Thanks! That doesn't crash now, but it doesn't delete revisions. Is there some sort of query log I can enable to see what its doing/not doing? Commented Nov 4, 2012 at 22:49
  • The delete sql was the problem, a string was empty. Now I have tested and it works. I have also created a plugin, easy to use after activation.
    – bueltge
    Commented Nov 5, 2012 at 13:19
  • Thanks! I was going to suggest a plugin. Works great; tested on my localhost and live site. (Edited a few typos in your answer). Commented Nov 6, 2012 at 1:21

I would prefer a different approach to achieve that. Rather than using the global $wpdb to directly access DB and delete revisions, I have used WP functions. The following code will delete revisions on Publish or Update of all post types that supports revisions and have a publish status:

add_action( 'admin_init', 'add_delete_revision_actions' );
function add_delete_revision_actions () {

    // get all post types, except 'revision'
    $post_types = get_post_types( array( 'exclude_from_search' => false ) );

    // add action for each post type that supports 'revisions'
    foreach ($post_types as $post_type) {
        if ( post_type_supports( $post_type, 'revisions' )) {
            add_action("publish_$post_type", 'delete_revisions_on_publish', 10, 1);

function delete_revisions_on_publish ($post_id) {

    // get revisions for this post
    $revisions = wp_get_post_revisions($post_id);

    // .. and delete it
    foreach ($revisions as $revision) {
        $delete = wp_delete_post_revision($revision->ID);
        // check for errors
        // if ( is_wp_error($delete) ) { ... }
  • This actually deletes all revisions on any post edit or publish. Commented Nov 4, 2012 at 2:14

It should be possible and it looks like you are on the right track.

To solve your "Call to a member function" error, I believe you need global $wpdb; at the top of that function.

I think the hook formerly know as publish_post would be a better hook for you as it is specific to published posts. save_post will run for all saves.

Also, you say that "the SQL query can run through all posts" but that will erase revisions for all drafts if you have more than one post in the works, or if you save an edit to a published post while you have a draft in the works. Anyway, that is your choice, but you don't need $wpdb->prepare at all if you do that. There is no input other than the hard coded SQL string so there is no need to 'prepare' anything.

    "DELETE a,b,c
    FROM wp_posts a
    LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id)
    LEFT JOIN wp_postmeta c ON (a.ID = c.post_id)
    WHERE a.post_type = 'revision' 
    AND a.ID = %d",
  • 1
    Thanks! I'm kind of a beginner at php. How would I implement {$new_status}_{$post->post_type}? And that's a good point about all other drafts; I need to just delete the revisions for the one post; so I need to pass the post_iD to the function? Commented Nov 2, 2012 at 13:03
  • In your case {$new_status}_{$post->post_type} would be publish_post -- status + post type. Yes, you should pass the post_ID in order to limit the query to only that post. I'll edit my answer to add that.
    – s_ha_dum
    Commented Nov 2, 2012 at 14:03
  • s_ha_dum, thanks for the suggestion; check out bueltge's plugin above. Commented Nov 6, 2012 at 12:58
  • @songdogtech seems you are expert rather than beginer of php:)
    – hugemeow
    Commented Nov 14, 2012 at 13:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.