SharePoint Online: Delete Version History using PnP PowerShell

Requirement: Delete version history in SharePoint Online.

How to Delete versions in SharePoint Online?

To delete previous versions of a file in SharePoint Online, follow these steps:

  • Navigate to your SharePoint Online document library, select the file and then click on “Version History” from the toolbar. (or Select “Version History” from the context menu of the document)
  • On the version history page, You can choose “Delete” from the context menu of the particular version. To delete all versions of a document or list item, in the Version History page, click the “Delete All Versions” link and then confirm the prompt.
    sharepoint online delete versions powershell

SharePoint Online: Delete Version History using PnP PowerShell

Let’s delete all versions of all items in a list or library using PowerShell.

#Config Variables
$SiteURL = "https://crescenttech.sharepoint.com/sites/marketing"
$ListName="Documents"

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential)

#Get the Context
$Ctx= Get-PnPContext

#Get All Items from the List - Exclude 'Folder' List Items
$ListItems = Get-PnPListItem -List $ListName -PageSize 2000 | Where {$_.FileSystemObjectType -eq "File"}

ForEach ($Item in $ListItems)
{
    #Get File Versions
    $File = $Item.File
    $Versions = $File.Versions
    $Ctx.Load($File)
    $Ctx.Load($Versions)
    $Ctx.ExecuteQuery()
    Write-host -f Yellow "Scanning File:"$File.Name
    
    If($Versions.Count -gt 0)
    {
        #Delete all versions
        $Versions.DeleteAll()
        $Ctx.ExecuteQuery()
        Write-Host -f Green "Deleted All Previous Versions of the File:"$File.Name
    }
}

PowerShell to Clear Previous Versions Folder by Folder

Here is a different approach to clear previous versions of all files.

#Parameters
$SiteURL = "https://crescent.sharepoint.com/sites/marketing"
$LibraryName ="Documents"

#Function to Clear all File versions in a Folder
Function Cleanup-Versions([Microsoft.SharePoint.Client.Folder]$Folder)
{
    Write-host "Processing Folder:"$Folder.ServerRelativeUrl -f Yellow
    #Get the Site Relative URL of the folder
    $FolderSiteRelativeURL = $Folder.ServerRelativeURL.Replace($Web.ServerRelativeURL,[string]::Empty)

    #Get All Files from the folder    
    $Files = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeURL -ItemType File
    
    #Iterate through each file
    ForEach ($File in $Files)
    {
        #Get File Versions
        $Versions = Get-PnPProperty -ClientObject $File -Property Versions 
        Write-host -f Yellow "`tScanning File:"$File.Name
     
        If($Versions.Count -gt 0)
        {
            #Delete all versions
            $Versions.DeleteAll()
            Invoke-PnPQuery
            Write-Host -f Green "`t`tDeleted All Previous Versions of the File:"$File.Name
        }
    }

    #Get Sub-folders from the folder - Exclude "Forms" and Hidden folders
    $SubFolders = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderSiteRelativeURL -ItemType Folder | Where {($_.Name -ne "Forms") -and (-Not($_.Name.StartsWith("_")))}
    Foreach($SubFolder in $SubFolders)
    {
        #Call the function recursively
        Cleanup-Versions -Folder $SubFolder     
    }
}
 
#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Interactive
$Web = Get-PnPWeb

#Get the Root Folder of the Library
$RootFolder = Get-PnPList -Identity $LibraryName -Includes RootFolder | Select -ExpandProperty RootFolder

#Call the function with Root Folder of the Library
Cleanup-Versions -Folder $RootFolder

You can clean up previous versions of all files from a folder by replacing Line#45 with “$RootFolder = Get-PnPFolder -Url $FolderServerRelativeURL”

Keep Last Five Versions and Delete the Rest:

Going through the version history page and deleting it one by one is cumbersome. Here is the PnP PowerShell to keep the last ‘N’ versions and delete all others.

#Config Variables
$SiteURL = "https://crescenttech.sharepoint.com/sites/marketing"
$ListName="Documents"
$VersionsToKeep = 5

#Connect to PnP Online
Connect-PnPOnline -Url $SiteURL -Credentials (Get-Credential)

#Get the Context
$Ctx= Get-PnPContext

#Get All Items from the List - Exclude 'Folder' List Items
$ListItems = Get-PnPListItem -List $ListName -PageSize 2000 | Where {$_.FileSystemObjectType -eq "File"}

ForEach ($Item in $ListItems)
{
    #Get File Versions
    $File = $Item.File
    $Versions = $File.Versions
    $Ctx.Load($File)
    $Ctx.Load($Versions)
    $Ctx.ExecuteQuery()

    Write-host -f Yellow "Scanning File:"$File.Name
    $VersionsCount = $Versions.Count
    $VersionsToDelete = $VersionsCount - $VersionsToKeep
    If($VersionsToDelete -gt 0)
    {
        write-host -f Cyan "`t Total Number of Versions of the File:" $VersionsCount
        #Delete versions
        For($i=0; $i -lt $VersionsToDelete; $i++)
        {
            write-host -f Cyan "`t Deleting Version:" $Versions[0].VersionLabel
            $Versions[0].DeleteObject()
        }
        $Ctx.ExecuteQuery()
        Write-Host -f Green "`t Version History is cleaned for the File:"$File.Name
    }
}

You can apply this cleanup to all files with in a specific folder or sub-folder by:

$ListItems = Get-PnPListItem -List $ListName -FolderServerRelativeUrl $FolderServerRelativeURL -PageSize 2000

This script leaves the recent ‘N’ number of versions and deletes all previous versions of the documents. To clean up older versions in SharePoint Online using PowerShell CSOM, refer: SharePoint Online: Delete Version History using PowerShell CSOM

Don’t forget to set a limit for the number of versions under:  List/Library Settings >> Versioning settings to prevent any further versions growing beyond your limit.

Salaudeen Rajack

Salaudeen Rajack is a SharePoint Architect with Two decades of SharePoint Experience. He loves sharing his knowledge and experiences with the SharePoint community, through his real-world articles!

28 thoughts on “SharePoint Online: Delete Version History using PnP PowerShell

  • Hello Salaudeen,

    thank you very much for the script. It has already helped me a lot to delete the old file versions (document library) within a single site collection (SharePoint Online). For it to work, it was necessary to add an extra Site Administrator account to the site and use those credentials for the script.

    I have run the script (case 3; keep 5 versions) on a test basis for a single site.
    https://example.sharepoint.com/teams/AAA

    Is there a way (via loop) to delete versions through all sites in a tenant?
    /teams/xxx
    /sites/xxx
    Using a sharepoint admin account (or global admin) without adding a separate site admin account to each individual team site (collection)?

    Supplemental question:
    After deleting the old versions on the test site (../teams/AAA), the SharePoint Online Admin Center does not show any reduction in memory usage.
    Is there a time delay here?

    Thanks for your help
    Greetings Tom

    Reply
    • 1. Even if you are a Global Admin, You must add your account as site collection Admin to each site in SharePoint Online, As there is no Web Application Policies in SharePoint Online.
      2. You can wrap this script inside a function and call the function for each site in your tenant.
      3. Yes! There is a time delay in recalculating the disk space!

      Reply
  • Accomplished my above request and have managed to cleanup most of our files. One File has 8000 versions and we get this error when when trying to clean it up: The request message is too big. The server does not allow messages larger than 2097152 and it errors out. How can you get it to work on a large set of versions.

    Also we were running into the time out issue. It cleans ups files but not all of them. We ended up just rerunning it until it was down to 100 versions.

    Reply
    • Yes! Larger requests may end up with timeout and related issues. You can mitigate by calling $Ctx.ExecuteQuery right after the operation such as: $Versions[0].DeleteObject()

      Reply
  • What if you have a CSV file with the Site Names and Library Names that have files over the limit. Can you read the sites from a CSV file?

    Reply
  • Hi, I’m running ‘PowerShell to Clear Previous Versions by Folder by Folder’

    Worked fine in my test environment of one folder level, but doesn’t run in my live environments with up to 20 folders depth.

    Could you let me know how many folders deep the script runs and if it can be adapted to run for all files and folders in a document library.

    Other than that, great script. Something Microsoft should have done !!!

    Reply
  • Hi, I’m running ‘PowerShell to Clear Previous Versions by Folder by Folder’

    Worked fine in my test environment of one folder level, but doesn’t run in my live environments with up to 20 folders depth.

    Could you let me know how many folders deep the script runs and if it can be adapted to run for all files and folders in a document library.

    Other than that, great script. Something Microsoft should have done !!!

    Reply
  • I am using a modified version of Keep Last Five Versions and Delete the Rest Script and its fantastic, my only problem is when the versions are large >100 as an example I get a timeout on the $Ctx.ExecuteQuery()

    Deleting Version: 2.137

    Exception calling “ExecuteQuery” with “0” argument(s): “The operation has timed out”

    I attempted to extend the time out by $Ctx.RequestTimeOut = 10000 or $Ctx.RequestTimeOut = 0 but the error still happens. Is there a way to execute them as batches?

    Reply
    • Try: $Ctx.RequestTimeout = [System.Threading.Timeout]::Infinite or call $Ctx.ExecuteQuery() after each Delete operation!

      Reply
    • Thanks very much for those options, I going to push my luck here.

      The request timeout didn’t work, I still get the same error. I am invoking it directly after this line 22 $Ctx.ExecuteQuery().

      If I try the other approach to run $Ctx.ExecuteQuery() inside here
      {
      write-host -f Cyan “`t Deleting Version:” $Versions[0].VersionLabel
      $Versions[0].DeleteObject()
      $Ctx.ExecuteQuery()

      }
      It doesn’t find the array item I am trying to remove and states that $Versions[0] is null.

      Am I missing something?

      Reply
    • Exception calling “ExecuteQuery” with “0” argument(s): “Cannot invoke method or retrieve property from null object. Object returned by the following call stack is null. “””

      is the exact error.

      Reply
  • Worked perfectly. Thank you!

    Reply
  • This comment has been removed by the author.

    Reply
  • Hi, can you just delete all versions but drop them into the recycle bin? DeleteAll permanently deletes them.

    Reply
  • I love most all your articles; however, this is one that did not work for me…at all. I had to enumerate through each version and $Version.DeleteObject()

    Received errors every time I used $Version.DeleteAll() [Method invocation failed because [Microsoft.SharePoint.Client.ListItemVersion] does not contain a method named ‘DeleteAll’]

    Reply
    • Well, Versioning features were added to PowerShell CSOM’s later build. I would suggest to update the PnP PowerShell module once and give it a try!
      Update-Module SharePointPnPPowerShellOnline

      Reply
    • That’s what I thought, too. I updated the module, but still nothing.

      I think this one’s a no-go for me, my friend. I still very much love the site – use it weekly!

      Thank you.

      Reply
    • The Version Collection object has DeleteAll(), But individual version has only DeleteObject() method!

      Reply
  • This comment has been removed by the author.

    Reply
  • Thank you for these!

    When using “Keep Last Five Versions and Delete the Rest” is there a way to specify the exact sub folder in a library? For example: .sharepoint.com/sites/marketing/documents/proposals/2019

    Reply
    • Use this line to get all files from a given folder:
      $ListItems = Get-PnPListItem -List $ListName -FolderServerRelativeUrl $FolderServerRelativeURL -PageSize 2000 | Where {$_.FileSystemObjectType -eq “File”}

      Reply
  • Hi this works a treat now you have done a great job on this thank you so much

    Reply
  • Hi there

    I ran the script but I get this message now

    Get-PnPListItem : The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator.

    Regards

    Eric

    Reply
  • I am getting the following errors, any idea?
    Exception calling “ExecuteQuery” with “0” argument(s): “Cannot invoke method or retrieve property from null object.
    Object returned by the following call stack is null. “File
    “”
    At line:10 char:5
    + $Ctx.ExecuteQuery()
    + ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ServerException

    Reply
    • Hey, I´ve got exactly the same problem. When I echo the $ctx variable I can see that the values for Versions and displayname are Null. Any way to fix that? :/

      Reply

Leave a Reply