# How to undo a bulk edit in Shopify

Updated 14 Sept 2026 · 14 min read · https://apimate.chat/blog/how-to-undo-bulk-edits-in-shopify

The Shopify admin has no undo for bulk edits. Once you save the bulk editor table or a CSV import finishes, the previous values are gone from Shopify. The product timeline records that an edit happened and by whom, not what the field was before. What you can do depends on what existed before the edit: an export you made, an app with a backup window, or a tool that saved the old value of every row at write time.

If none of those exist, the previous values live in your memory, in order confirmations, in Google's cache and in the supplier's price list. That is a reconstruction, not a revert. It is doable for prices on a hundred products and not for descriptions on a thousand. The order of steps below is the order of cost: each one is cheaper than the next, and the first one is free.

The long-term fix is to never run a bulk edit without a way back. That is either an export you keep, or a tool that stores the before value of every row it writes and builds the revert from them. The last section is about that.

## What the admin gives you

Nothing, for values. The bulk editor writes when you save. A CSV import overwrites every column in the file. The product timeline (the activity feed at the bottom of a product page) shows that a product was edited, when, and by which staff account or app, but not the previous value of the field. There is no version history for products, variants or metafields.

Two partial exceptions. A CSV import can be cancelled from the import status page while it is still running; rows already written stay written. And Shopify's own backup of your store exists for disaster recovery, not for per-field restores; support will not roll your catalog back to Tuesday because a price edit went wrong.

Some fields keep their own history. Inventory has an adjustment history per variant per location, visible in the admin, which tells you what the quantity was before the edit. Orders are not bulk edited in the same way and keep their own timeline. For prices, titles, descriptions, tags, SEO fields and metafields, there is no admin history to read.

Sources: [Shopify Help: bulk editing](https://help.shopify.com/en/manual/shopify-admin/productivity-tools/bulk-editing), [Shopify Help: importing products with a CSV](https://help.shopify.com/en/manual/products/import-export/using-csv)

## First: find the scope

Before fixing anything, know what changed. A second bulk edit that "fixes" the first without knowing its scope is how one bad edit becomes two. The admin can tell you the scope even though it cannot tell you the values.

Products, filter by "Updated" in the last hour (or whatever window covers the edit). That list is everything the edit touched, plus anything else that changed in the same window: an order that adjusted stock, an app that synced. Export it. That export is the "after" snapshot, and you will want it later to confirm the restore covered every row.

If the edit was a CSV import, the import status page shows how many rows succeeded and lists the failures. If it was an app, the app's task history shows the target set. If it was a tool with job history, the job's preview is the scope. Write the count down. The restore is done when that many rows are back.

- Stop. No second edit until the first is scoped.
- Products, filter "Updated: last hour". Export the list.
- Note the count and the fields touched.
- Check the same window for orders and app syncs that also changed values.

## Option one: re-import an export

If you exported the products before the edit, the export has the previous values. Re-importing it puts them back. This is the cheapest real revert and the one the Shopify help pages point at, and it has three traps.

The export restores every column in the file, not just the one you broke. If you changed titles on purpose on Tuesday and broke prices on Wednesday, a re-import of Monday's export restores Monday's titles too. Open the file, delete every column except the identifiers (Handle, Variant SKU or Variant ID) and the columns you want back, then import. A file with fewer columns is a safer file.

Tags in the CSV replace the product's tags; they do not add. Inventory in the export is the quantity at export time, not now, and any sales since then are not in it; treat a restored quantity as a starting point and reconcile against the adjustment history. And an empty cell in a column you kept clears that field on import. Check the file for blanks before you upload it.

The import runs in the background and takes a while for a large file. When it finishes, open five products from the scope list and read the field. Then compare the row count in the import status to the count you wrote down.

- Keep only identifier columns plus the columns to restore.
- Check for empty cells in the kept columns; a blank clears the field.
- Tags replace. Inventory is stale. Both need a second look.
- Verify five products by eye and the row count against the scope.

## Option two: an app with a backup window

If the edit ran through a bulk-edit app, the app may keep a backup of the affected records for a window. Ablestar keeps 60 to 180 days of task history depending on plan; Hextom 30 to 180. Matrixify does not keep a backup; its revert is a re-import of an export you made. QuickEdit has undo and revert on paid tiers. Check the listing for the current numbers; they change.

The app's undo restores what the app wrote, from its own copy of the before values. That is better than a CSV re-import in one way: it restores exactly the rows and fields of that task, nothing else. It is worse in one way: it is only as complete as what the app captured. If the app wrote a field it does not back up, that field is not coming back through the app.

The edit has to have gone through the app for this to work. An app cannot undo a change made in the admin bulk editor or by a CSV import, because it never saw the before values. This is the most common disappointment on the support threads: a merchant installs an undo app after the mistake and finds it has nothing to undo.

## Option three: revert from saved before values

Some tools save the previous value of every row at the moment they write it, and build the revert from those values as a new job. This is the strongest shape, because the before values are captured per row, at write time, for exactly the fields written. There is no export to have made and no window to have missed.

In ApiMate each job stores the before value per row. "Revert the price job from this morning" produces a preview: one row per variant, the value it has now, the value it will be restored to. You approve it like any other write. If something else changed a row since the job (an order took stock, another job edited the same field), the preview shows the current value so you can see the collision before it is written.

What this cannot revert is creation and deletion. A product that did not exist has no before value; a variant that was deleted took its id and its order history with it. Both are labelled as one-way in the preview before the job runs, which is the point: the time to know a change is one-way is before it.

> **Instruction** Revert this morning's price job on Cedar & Pine. Show me the rows where the current value is not the one the job wrote.

## Option four: fix forward

No export, no app history, no saved before values. The previous values now exist only outside Shopify. This is reconstruction, and it is worth doing systematically rather than product by product.

For prices, the sources are the supplier's price list, the last order that sold each variant (the order line item stores the price at the time of sale), any price feed (Google Merchant Center keeps the last crawled price per product), and the wholesale catalog. For titles and descriptions, Google's cache of the product page and the Wayback Machine. For tags, the collection rules: a product that should be in the "Winter" automated collection tells you it had the tag. For inventory, the adjustment history per variant.

Build a sheet with one row per affected variant, fill the columns from the sources, and import it as a CSV with only those columns. Then run the audit again. It is slower than any of the three options above and it is not exact, and it is what is left.

| Field | Where the old value may still be | How exact |
| --- | --- | --- |
| Price | Last order line item per variant; supplier list; Merchant Center | Exact if sold recently |
| Compare-at price | Merchant Center sale price; theme cache | Approximate |
| Inventory | Adjustment history per variant per location | Exact |
| Tags | Automated collection rules; theme cache | Partial |
| Title, description | Google cache; Wayback Machine; the supplier | Partial to exact |
| SEO title, meta description | Search result snippets; Wayback | Approximate |
| Metafields | The supplier sheet they came from; nowhere else | Exact if the sheet exists |
| Alt text | Nowhere reliable | Rewrite |

_Reconstruction sources by field. The inventory row is the only one the admin itself keeps._

## Field by field: what a revert restores

A revert is not one thing. Each field has a shape, and the shape decides whether "put it back" is exact or approximate. Knowing this before the edit is how you decide whether the edit needs an export first.

- Price and compare-at: a value per variant. Exact revert if the before value was saved. The trap is a compare-at that was empty before and is now set; "revert" has to clear it, not set it to zero.
- Inventory: a quantity per variant per location, and it moves on its own with orders. A revert restores the number at the time of the edit; sales since then are lost unless the revert is an adjustment (subtract what the edit added) rather than a set.
- Tags: a list per product. A revert has to restore the list, not remove the tag you added, because the edit may have replaced the list. CSV imports replace; most apps add.
- Status: active, draft, archived. Exact. The side effect is not: a product set to draft dropped out of the Google feed and comes back on the next crawl, not the moment you revert.
- Descriptions: one HTML blob per product. Exact if saved whole. A revert of a find-and-replace is not the reverse find-and-replace; it is the whole previous description.
- Metafields: typed values. Exact if saved with the type. A revert that writes a string into a dimension field fails.
- Variants and options: structural. Renames revert; deletes do not, because the id is gone.
- Images: attachments and positions. A removed image is gone from the product but may still be in Files; re-attach by hand.

## What a bad bulk edit usually looks like

Four patterns account for most of the "how do I undo" threads. Recognising which one you are in tells you which option above applies.

The filter matched more than intended: a tag rule with prefix matching, or drafts included. Scope is the fix, and the scope is in the "Updated" filter. The rule was applied at the wrong level: a percent meant for variants applied per product, or a price written to every variant instead of the one size. The values are wrong in a predictable way, which makes fix-forward easier. The file lost a column: SKUs lost leading zeros, barcodes became scientific notation, images cleared. The damage is in the columns you did not think you were importing. And the job half-applied: some rows have the new value, some the old, and a second run would double-apply the rule to the rows that succeeded.

The half-applied job is the one where "run it again" does the most damage. Find the rows that did write (the "Updated" filter, or the job's per-row report), and scope the fix to the rest.

## Before the next bulk edit

Every option above is cheaper if you set it up before the edit. Four habits cover most of it.

Export first, every time, even for a small edit. It takes a minute and it is the only revert the admin supports. Keep the export for at least as long as it would take to notice the mistake, which is longer than you think; a quarterly review finds edits from three months ago. Use a tool that saves the before values per row and previews the revert; that removes the export step for the jobs it runs. And run the small test: ten products, the real rule, then revert, before the full catalog.

For inventory specifically, prefer adjustments over sets when the edit is relative ("add 20 to every variant") so a revert is the opposite adjustment and sales in between are preserved.

- Export before. Keep it ninety days.
- Prefer a tool with per-row saved before values and a revert preview.
- Ten products first, then revert, then the catalog.
- Inventory: adjust, do not set, when the change is relative.
- Know the one-way changes (delete, create) before approving them.

## Other ways to ask this question

These all land on the same four options.

- "I bulk edited prices and they are all wrong, how do I get the old prices back?"
- "CSV import overwrote my product descriptions."
- "Shopify bulk editor undo button?"
- "Does Shopify have product version history?"
- "An app changed all my tags, can I revert?"
- "I set every product to draft by accident."
- "Import cleared my product images."

## Terms used on this page

- Bulk editor: the table view in the Shopify admin for editing several products at once. Saves on click; no undo.
- Product timeline: the activity feed on a product page. Records that an edit happened, not the previous value.
- Backup window: how long a bulk-edit app keeps the before values of a task. Plan-dependent.
- Before value: the value of a field immediately before a write. A revert needs it; the admin does not keep it.
- Adjustment history: the per-variant, per-location log of inventory changes in the admin. The one field history Shopify keeps.
- Fix forward: reconstructing previous values from outside sources when no revert exists.
- One-way: a change no revert covers. Deleting a variant, creating a product.

## Questions

### Can I undo a Shopify bulk editor change?

Not in the admin. Restore from a CSV export made before the edit, from an app with a backup window if the edit went through that app, or from a tool that saved the previous values per row.

### Can I cancel a CSV import?

While it is running, yes, from the import status page. Rows already written stay written. After it finishes, no.

### Does Shopify keep a version history of products?

No. The timeline records that an edit happened and by whom. Inventory has an adjustment history per variant per location; other fields have nothing.

### Will Shopify support restore my products?

Shopify's backups are for disaster recovery of the platform, not per-store, per-field restores. Support will not roll back a price edit.

### Can an undo app revert an edit I made in the admin?

No. An app can only undo what it wrote, because that is when it captured the before values. Installing an undo app after the mistake gives it nothing to undo.

### How do I find which products a bulk edit touched?

Products, filter by Updated in the window of the edit. Export that list as the after snapshot and note the count.

### What about inventory that changed since the edit?

A restored quantity is the number at the time of the export or the job. Reconcile against the adjustment history, or prefer adjustments over sets so the revert is the opposite adjustment.

### What cannot be reverted at all?

Deleted variants (the id and its order history are gone) and created products (there is no before). Both should be labelled one-way in a preview before you approve them.

## Related

- [Bulk update prices and inventory in Shopify, with undo](https://apimate.chat/cases/shopify-bulk-update-prices): What revert restores for prices, compare-at prices and stock.
- [Shopify bulk editor vs CSV vs API](https://apimate.chat/blog/shopify-bulk-editor-vs-csv-vs-api): Which layer to use so the next bulk edit has a way back.
- [Best Shopify bulk product editor](https://apimate.chat/best-shopify-bulk-product-editor): Undo windows and preview shapes across five tools.
