Azure Devops – Managed Branch Policies – Default Branch
When working with large Azure DevOps projects containing many repositories, setting up consistent branch policies across all default branches can be a challenge—especially when targeting dynamically named default branches (like main, master, etc.).
The Problem
Azure DevOps branch policies are typically set per branch (e.g., refs/heads/main), which means hardcoding values that may not be consistent across repositories.
The Solution
Instead of hardcoding branch names, you can use the DefaultBranch match kind when configuring branch policies via the REST API. This approach ensures the policy always applies to each repository’s default branch—no matter what it’s named.
Understanding the Key Setting
In the REST API, the "matchKind": "DefaultBranch" setting within the scope array makes the policy apply to whatever the default branch is for each repository.
"scope": [
{
"repositoryId": null,
"refName": null,
"matchKind": "DefaultBranch"
}
]
This is powerful because:
repositoryId = null→ Applies to all repositories.refName = null→ Applies to all branches.matchKind = "DefaultBranch"→ Filters the scope to only the default branch of each repository.
Example PowerShell Code
Here’s a PowerShell snippet using the Azure DevOps REST API to apply a merge strategy policy to default branches across all repositories:
$MergeStrategyId = "fa4e907d-c16b-4a4c-9dfa-4916e5d171ab" # Policy Type: Merge Strategy
$MergeStrategyBody = @{
isEnabled = $true
isBlocking = $true
type = @{
id = $MergeStrategyId
}
settings = @{
allowNoFastForward = $false
allowSquash = $true
allowRebase = $false
allowRebaseMerge = $false
creatorVoteCounts = $false
scope = @(
@{
repositoryId = $null
refName = $null
matchKind = "DefaultBranch" # Applies to the default branch of each repo
}
)
}
} | ConvertTo-Json -Depth 10
Don’t forget to authenticate your request using a personal access token (PAT) or service connection.
Then post the policy with something like:
$Project = "your-project-name"
$Org = "https://dev.azure.com/your-org"
$Uri = "$Org/$Project/_apis/policy/configurations?api-version=7.0"
Invoke-RestMethod -Uri $Uri -Method Post -Body $MergeStrategyBody -ContentType "application/json" -Headers @{ Authorization = "Basic $base64AuthInfo" }
Final Tips
- You can retrieve existing policies via the REST API to reverse-engineer the correct settings (
GET _apis/policy/configurations). - Replace
"fa4e907d-c16b-4a4c-9dfa-4916e5d171ab"with other policy type IDs depending on your policy goals (e.g., reviewer count, build validation). - Always test on a test project or repo first to ensure the policy behaves as expected.
- Use Get to get list of policies and then Put if any existing policy is already present that you want to update, because you need the policy Id to Put (update)