How to Delete File and List Versions in SharePoint: Quick Overview


SharePoint versioning is genuinely useful — every edit gets its own recoverable snapshot — but nobody ever prunes it by default. A library with hundreds of edits per file over a few years can be carrying gigabytes of version history nobody’s looked at, pushing storage usage up and query performance down. Cleaning it up periodically is routine maintenance, not an edge case.


In this post: Major vs minor versions · Prerequisites · PowerShell for SharePoint Online · PowerShell for SharePoint On-Premises · Best practices · When would you actually use this? · Related reading


Major vs minor versions

Major versions (1.0, 2.0, 3.0) represent published, official states of a document — one gets created every time you save, in libraries where that’s the only versioning mode enabled. Minor versions (1.1, 1.2) track interim drafts, and only appear when content approval is turned on — they’re visible to editors, not to everyone with just read access. Both count toward the version total that eventually needs pruning; minor versions especially, since drafts accumulate faster than published saves.


Prerequisites
  • Full Control or Site Collection Administrator permissions — version deletion isn’t available at lower permission levels.
  • A backup of the library or list before running anything in bulk. Deleted versions aren’t recoverable from the Recycle Bin the way a deleted item is.
  • PnP.PowerShell installed for SharePoint Online, or the SharePoint Management Shell / snap-in for on-premises.
  • A decided retention number before you start — most organizations settle on keeping 5-10 major versions and pruning the rest, but pick a number deliberately rather than defaulting to whatever the script happens to use.

PowerShell for SharePoint Online
# Install PnP PowerShell Module (if not installed)
# Install-Module -Name "PnP.PowerShell" -Scope CurrentUser

# Connect to SharePoint Online
$siteUrl = "https://yourtenant.sharepoint.com/sites/yoursite"
Connect-PnPOnline -Url $siteUrl -Interactive

# Set variables
$libraryName = "Documents"
$keepVersions = 5

# Get all items in the library
$items = Get-PnPListItem -List $libraryName -PageSize 500

foreach ($item in $items) {
    $file = Get-PnPFile -Url $item.FieldValues["FileRef"] -AsListItem
    $versions = $file.Versions

    if ($versions.Count -gt $keepVersions) {
        # Delete from the end backward -- deleting forward by index while the
        # collection re-indexes on the server can skip entries.
        for ($i = $versions.Count - 1; $i -ge $keepVersions; $i--) {
            $label = $versions[$i].VersionLabel
            $versions[$i].DeleteObject()
            Invoke-PnPQuery
            Write-Host "Deleted version $label of $($file.Name)"
        }
    }
}
Disconnect-PnPOnline

One change from how this is often written: delete from the highest index down to $keepVersions, not the other way around. Deleting forward while the version collection re-indexes on each Invoke-PnPQuery call can silently skip versions — going backward avoids that entirely.


PowerShell for SharePoint On-Premises
# Load SharePoint Snap-in
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

# Variables
$webUrl = "http://yoursite"
$listName = "Documents"
$keepVersions = 5

# Get the web and list
$web = Get-SPWeb $webUrl
$list = $web.Lists[$listName]

# Loop through items and delete old versions, newest-kept to oldest
foreach ($item in $list.Items) {
    if ($item.Versions.Count -gt $keepVersions) {
        for ($i = $item.Versions.Count - 1; $i -ge $keepVersions; $i--) {
            $item.Versions[$i].Delete()
        }
        $item.Update()
        Write-Host "Deleted old versions for: $($item.Name)"
    }
}

$web.Dispose()

Best practices
  • Test against a sandbox site or a copy of the library first — version deletion has no undo, and running an untested script against production is how “clean up old versions” becomes an incident.
  • Automate it on a schedule rather than running it manually whenever storage complaints come in — version bloat is continuous, not a one-time cleanup.
  • Set a version limit in library settings (Versioning Settings > “Keep the following number of major versions”) as the long-term fix — scripts handle the backlog, but a configured limit prevents it from recurring.
  • Check for workflow or approval dependencies before bulk deletion — some processes reference specific version numbers, and deleting under them can break more than storage.

Set a version limit in library settings as the actual fix — scripts clean up the backlog, but only a configured cap stops it from building up again.

When would you actually use this?
  • SharePoint Online storage is creeping toward its quota and a handful of heavily-edited libraries are the likely cause.
  • A large list or library has gotten noticeably slower to load, and version count is a plausible contributor worth ruling out.
  • Compliance requires that only a defined retention window of versions exists, not an unbounded history.


That’s the cleanup covered. Comment below if your version counts still look off after running this.


App Catalog Authentication Automation Backup Compliance Content Type CSS Flows Google Javascript Limitations List Metadata MFA Microsoft Node NodeJs O365 OneDrive Permissions PnP PnPJS Policy PowerApps Power Automate PowerAutomate PowerPlatform PowerShell React ReactJs Rest API Rest Endpoint Security Send an HTTP Request to SharePoint SharePoint SharePoint List SharePoint Modern SharePoint Online SPFX SPO Sync Tags Teams Termstore Versioning

Leave a Comment

Your email address will not be published. Required fields are marked *