How to Create an Undo Group in GIMP Scripts

This guide explains how to bundle multi-step operations in GIMP into a single undo step using undo groups. By implementing undo groups in your custom Python-Fu or Script-Fu scripts, you ensure that complex, multi-action modifications can be cleanly reverted with a single undo command (Ctrl+Z), preventing the undo history from becoming cluttered and protecting the user's workflow.

Why Use an Undo Group?

By default, every modification a script makes—such as creating a layer, applying a blur filter, or transforming a selection—creates an individual entry in GIMP’s Undo History. A script executing ten separate actions forces the user to press undo ten times to revert the canvas to its original state.

An undo group treats all procedural operations between its start and end markers as a single atomic event.


Python-Fu Implementation

In Python-Fu (standard in GIMP 2.8 and 2.10), undo groups are managed either via the image object directly or through the Procedural Database (PDB).

1. The Core Methods

To open and close the group:

  • Start: image.undo_group_start() or pdb.gimp_image_undo_group_start(image)
  • End: image.undo_group_end() or pdb.gimp_image_undo_group_end(image)

2. Using try...finally for Safety

Always enclose operations in a try...finally block. If an unhandled exception occurs while an undo group is open, GIMP's undo stack can become corrupted or permanently locked. The finally clause guarantees that the undo group closes regardless of errors.

def my_custom_script(image, drawable):
    # Begin the undo group
    image.undo_group_start()
    
    try:
        # Step 1: Add a new layer
        new_layer = pdb.gimp_layer_new(image, image.width, image.height, 
                                       RGBA_IMAGE, "Processed Layer", 100, NORMAL_MODE)
        pdb.gimp_image_insert_layer(image, new_layer, None, 0)

        # Step 2: Fill the layer
        pdb.gimp_drawable_fill(new_layer, WHITE_FILL)

        # Step 3: Apply an effect
        pdb.plug_in_gauss(image, new_layer, 10.0, 10.0, 0)
        
    finally:
        # Always close the undo group
        image.undo_group_end()

Script-Fu (Scheme) Implementation

In Script-Fu, use the standard PDB functions gimp-image-undo-group-start and gimp-image-undo-group-end.

(define (script-fu-my-operation image drawable)
  ;; Start the undo group
  (gimp-image-undo-group-start image)

  ;; Multi-step operations
  (let* ((new-layer (car (gimp-layer-new image 
                                         (car (gimp-image-width image)) 
                                         (car (gimp-image-height image)) 
                                         RGBA-IMAGE 
                                         "Script Layer" 
                                         100 
                                         LAYER-MODE-NORMAL))))
    (gimp-image-insert-layer image new-layer 0 0)
    (gimp-drawable-fill new-layer FILL-WHITE)
  )

  ;; End the undo group
  (gimp-image-undo-group-end image)
  (gimp-displays-flush)
)

Best Practices

  • Pair Every Call: Every call to undo_group_start must have a matching undo_group_end. Nesting is supported, but mismatched calls will cause abnormal undo behavior.
  • Do Not Disable Undo: Avoid using gimp_image_undo_disable() unless working on temporary scratch images. Disabling undo clears the existing history entirely, preventing the user from undoing prior work.
  • Flush Displays After Closing: Call gimp_displays_flush() after undo_group_end() to update the UI only after all steps are finalized.