Limit Versioning and Delete Old Versions in SharePoint

In one of my SharePoint implementation, Defined the governance policy for versioning as: “Only 5 Major and 5 Minor versions should be kept.”. So placed that in End-user self-service Portal site. But who cares? users setup up their document libraries/Lists to an unlimited number of versions, and asking for Increasing the Site quota quite often.

On analyzing the site space figured out: For a 1GB site, versions are occupying nearly 300MB!!! So, I wanted to clean-up the versions except for the last 5 minor/Last 5 Major. Oh, Yeah, to set versioning limit in SharePoint, Just get into the List/Library settings > Versioning settings then setup the versioning limits.

Limit Versioning and Delete Old Versions in SharePoint

Quite simple, Isn’t it? Ah, but the user has 100+ libraries where unlimited number of versions enabled! OMG!!!

Limit number of versions in SharePoint with PowerShell

PowerShell comes to rescue again! Here is the code to delete the older versions, except the last 5 major and minor.

$SPsiteCollection = Get-SPSite "https://SharePointSite.com"  
# Loop through all Webs in the Site Collection  
foreach($SPweb in $SPsiteCollection.AllWebs)   
{  
	#loop through all lists in web
	foreach ($SPlist in $SPweb.Lists)
	{  
	   if($SPlist.EnableVersioning -eq $true)
	   {
			 write-host "Setting versioning Limit for :" $SPlist.title 
			 $SPlist.MajorVersionLimit = 5;
			 # To Disable Versioning use: $SPlist.EnableVersioning=$false
			 # To Enable Minorversion: $SPlist.EnableMinorVersions = $true;
			 # Minor version Limit:  $SPlist.MajorWithMinorVersionsLimit = 5;

			 $SPlist.Update();
	   }
	}
}

How to Disable Versioning in a SharePoint List?

In case, You want to disable version history for a particular list or library, use this PowerShell script:

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
#Define variables
$WebURL="https://sharepoint.crescent.com"
$ListName="Projects"

#Get the web and List
$web = Get-SPWeb $WebURL
$List = $web.Lists[$ListName]

#Disable Versioning 
$List.EnableVersioning = $false
$List.Update()

#Delete all existing versions of all list items
ForEach($item in $list.Items) 
{
   $item.URL;
   $item.SystemUpdate();
}

Ok, What about cleaning the Old versions?
I have set-upped versioning limits, Will it delete the older version beyond my limit? Unfortunately “NO”!

Say for e.g. I have a Document in Document Library with an unlimited number of versions turned ON, Where the document has 20 versions. So, If I Set the versioning limit to 5, will it delete the Older 15 versions and Keep only the last 5? NO NO NO, Until we create a new document or edit the existing document, those versioning limits will not be applicable. This new limit will not affect the existing old version. We need to Delete them explicitly.

Take a Look at this task list, where I’ve limited the versions NOW to 3, But it has existing older versions!

Limit Cleanup SharePoint Versioning

Programmatically delete old versions with PowerShell

So, To clean up the existing versions, Let us seek help from PowerShell again! Let the PowerShell delete older versions.

$SPweb = Get-SPWeb "https://SharePointSite.com"
$versionsToKeep =5;
$SPlist = $SPweb.Lists["Tasks"]
foreach ($SPitem in $SPlist.Items)
{
	$currentVersionsCount= $SPItem.Versions.count

	if($currentVersionsCount -gt $versionstoKeep)
	{
		for($i=$currentVersionsCount-1; $i -gt $versionstoKeep; $i--)
		{
			$SPItem.versions[$i].delete()
		}
	}
}

Alternatively, You can perform an empty update in list items to apply the new versioning limit and cleanup older versions.

$SPweb = Get-SPWeb "https://sharepoint.crescent.com"
$versionsToKeep =3;
$SPlist = $SPweb.Lists["Tasks"]

foreach ($SPListItem in $SPlist.Items)
{
   $currentVersionsCount= $SPListItem.Versions.count

   if($currentVersionsCount -gt $versionstoKeep)
   {
        $SPListItem.SystemUpdate()
   }
}

When you have a large number of versions in the SharePoint list, iterating through versions may result in performance hits. So, the alternate method goes below:

#Variables for Processing
$WebURL = "https://sharepoint.crescent.com/operations/imphilippineswksp/QII/"
$ListName ="Project Cost"
$ItemID="512"

#Get the Web and List objects
$web = Get-SPWeb($WebURL)
$list = $web.Lists[$ListName]

#Set list version setting
$list.MajorVersionLimit = 10
$list.Update() 

#Get the List Item
$item = $list.GetItemById($itemId)
 
#Perform a empty update - without creating new version, so that versioning changes will take effect
$item.SystemUpdate($false) 

write-host "Total Number of versions Now:"$Item.Versions.count
 
#Dispose 
$web.dispose();

Update: I’ve created a utility to limit and cleanup old versions of documents. You can download it here: SharePoint Versioning Manager – Control Versioning Settings & Clean-Up Old Versions

Salaudeen Rajack

Salaudeen Rajack - Information Technology Expert with Two-decades of hands-on experience, specializing in SharePoint, PowerShell, Microsoft 365, and related products. He has held various positions including SharePoint Architect, Administrator, Developer and consultant, has helped many organizations to implement and optimize SharePoint solutions. Known for his deep technical expertise, He's passionate about sharing the knowledge and insights to help others, through the real-world articles!

16 thoughts on “Limit Versioning and Delete Old Versions in SharePoint

  • Hello There

    I have deleted a lot of the Version History manually for a MySite user. However the quota warning is not disappearing, and it still states “0.00 GB free of 4.88 GB” which is not true because in total user has used up 3.26GB of 5GB.

    How do I clear out this log ?
    I have tried to increase the Quoata and reduce it again?

    Please advise.
    We use SP 2016 OnPrem and have access to Central Admin.

    Reply
  • This is a great script – thanks for sharing! After running for a large Web Application, I’m seeing the overall size reduced around 250GB (using Microsoft’s SMAT); however, the content DB is only showing about 50GB free space. Do you know why I wouldn’t see the size reduction reflected in the Content DB?

    Reply
    • Well, If you have deleted the versions or performed update operation after setting up new versioning limits, that should gain you free space. After a massive delete/cleanup operations, it’s a good idea to defrag the database and do log cleanup.

      Reply
  • $item.SystemUpdate() is not able to reflect the changes to items in the library. Any other suggestion as I have to implement this setting to all the libraries in my farm

    Reply
  • interesting power shell script would it be possibel to make a script where you can define the number of versions and when reached that level it will automatically delete the oldest version and ad the newest.
    A rule like First one in last one out 🙂 this would be very functional and very handy .
    Any ideas some one ?

    Reply
  • How can I use the script (Alternatively, You can perform an empty update in list items to apply new versioning limit and cleanup older versions) in Sharepoint-Online?

    Reply
  • Is there a table or list where the version information is stored and if so do you know the URL?

    Reply
  • Note, the equal sign = is a assignment in powershell for genuine comparison operations you need -eq. This line: if($SPlist.EnableVersioning=$true) will always be true. Needs to be if($SPlist.EnableVersioning -eq $true)

    Reply
  • Had to tweek a couple of things, but this saved me days of work. Thanks a bunch!

    Reply
  • When I try to delete old versions, getting the below error. Any idea.

    You cannot call a method on a null-valued expression.
    At E:testVers_del.ps1:53 char:53
    + $Item.Versions[770.0].delete <<<< () + CategoryInfo : InvalidOperation: (delete:String) [], RuntimeException + FullyQualifiedErrorId : InvokeMethodOnNull

    Reply
  • Shouldn’t the line:

    for($i=$currentVersionsCount-1; $i -gt $versionstoKeep; $i–)

    Instead be:

    for($i=$currentVersionsCount-$versionstoKeep; $i -gte 1; $i–)

    For instance, if there are 20 versions and you want to keep 5 this would start with version 15 and delete older versions (lower number versions) through version 1.

    It seems the line you used would delete all but the oldest 5. Am I reading it wrongly?

    Reply
    • Hi there,

      The above code aims to keep the latest versions and delete the old one. Versions are stored as First-in-first-out.

      Reply
    • For the 2016-version, it seems that the:
      for($i=$currentVersionsCount-$versionstoKeep; $i -gte 1; $i–)

      is the correct code..

      Reply
  • How will be the script for minor versions?

    Reply
    • You can set List.EnableMinorVersions and list.MajorWithMinorVersionsLimit properties.

      Reply

Leave a Reply

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