How to Delete Stale Branches in Azure DevOps with PowerShell

stale branches

If you’re managing a large Azure DevOps repository with many branches, it can be challenging to keep the list clean and manageable. In cases where you have numerous branches, you might have a hard time finding a relevant branch, particularly if you haven’t touched it in quite some time. To help solve this problem, there is a PowerShell script that can help sort all your stale branches in a single swoop. The script will identify and delete any branch that hasn’t been modified for a specific number of days. This process will help keep your branch list well-organized and free up some hard drive space by removing obsolete branches.

The complete powershell script can be found below.

Explaining the PowerShell Script

Here is the explanation of each line in the PowerShell script provided:

$project = "<ProjectName>"
$repository = "<repoName>"
$organization = "<OrganizationName>"
$excludeBranches = @("develop","master","qa") #Provide any branch names that needs to be excluded
$daysDeleteBefore = -30 #Provide number of days
$dateTimeNow = [DateTime]::Now
$dateTimeBeforeToDelete = $dateTimeNow.AddDays( $daysDeleteBefore)

if (-not (Test-Path env:IS_DRY_RUN)) { $env:IS_DRY_RUN = $true }
Write-Host ("is dry run: {0}" -f $env:IS_DRY_RUN)
Write-Host ("datetime now: {0}" -f $dateTimeNow)
Write-Host ("delete branches before {0}" -f (get-date $dateTimeBeforeToDelete))

The above code defines the parameters for Azure DevOps repositories and sets the exclusion branches parameter as well. The number of days before a branch should be deleted is also specified using the $daystoDeleteBefore parameter. This value can be adjusted to meet your specific needs. The system time and the time frame for deletion are both displayed using the Write-Host command.

$refs = az repos ref list --project $project --repository $repository --organization $organization --filter heads | ConvertFrom-Json

The code above gets the list of branches available in the repository by running the “az repos ref list” command with the necessary parameters.

$toDeleteBranches = @()
foreach ($ref in $refs) {

The above code sets an empty array named $toDeleteBranches, which will be used to store branches to be deleted. The foreach loop is used to iterate through all the branches fetched earlier.

if ($ -replace "refs/heads/" -in $excludeBranches) {

This code checks the name of each branch to see if it’s in the excluded list, and if it is, the branch is skipped.

$commit = az devops invoke `
--area git `
--resource commits `
--organization $organization `
--route-parameters `
project=$project `
repositoryId=$repository `
commitId=$objectId | ConvertFrom-Json

The code above invokes the Git area of the DevOps API to obtain the date that each branch was last modified, which is essential when identifying stale branches.

$toDelete = [PSCustomObject]@{
name = $
creator = $ref.creator.uniqueName
lastAuthor = $
lastModified = $
objectId = $objectId
$toDeleteBranches += , $toDelete

This code creates an object with the properties required for branch identification and removal, such as name, creator, author, last_modified, and so forth.

$toDeleteBranches = $toDeleteBranches | Where-Object { (get-date $_.lastModified) -lt (get-date $dateTimeBeforeToDelete) }

The above code utilizes the Where-Object feature from PowerShell to analyze the last_modified property of each branch and deletes it if it is found to be stale.

$filename = $repository + "__StaleBranches.csv"
$toDeleteBranches | ConvertTo-Csv -UseQuotes AsNeeded > ./$filename

The above code creates a CSV file to serve as a backup if code deletions go wrong.

if (![System.Convert]::ToBoolean($env:IS_DRY_RUN)) {

$result = az repos ref delete `
--name $ `
--object-id $_.objectId `
--project $project `
--repository $repository |

Write-Host ("success message: {0}" -f $result.updateStatus)

The above code is responsible for deleting branches that are discovered to be stale. It uses the environment variable $env:IS_DRY_RUN, which must be set to $false for code deletions to occur.

How to Use the Script

Before executing the script, add your Azure DevOps repositories and parameters, such as project name, repository name, and organization name. Additionally, you can specify the branches to be excluded by modifying the $excludeBranches array with the proper branch names.

Once that’s complete, access PowerShell from the command line and navigate to the directory where the script is saved. Finally run:


The script will display information about your organization’s current state, as well as the list of branches that the script is about to delete. By default, the $env:IS_DRY_RUN environmental variable is set to true, which allows the script to run as dry-run mode. This command simulates the deletion process without making any changes to your repos. If you’re satisfied with the results, change this variable to $false before re-running the script to delete stale branches permanently:

$env:IS_DRY_RUN = $false

Why Use the Script

The Delete Stale Branches script can save you significant time and effort when it comes to organizing repositories. You can get the complete script from below link.

Credit for orginal script:

You may also like...

Leave a Reply