Set the Default Branch on your Azure DevOps Repos

Lets talk Azure DevOps Repos!

Introduction

« Breaking News » the Git project has decided to use as default branch main instead of master.

Git default branch

As very well described in the following article, Microsoft has set on november 2020 the default branch of all new Azure DevOps Repos to be main instead of master.

“Microsoft is joining the Git project (statementcode change) and multiple vendors including GitHub in delivering these changes. As an industry, we’re making an effort to move towards more inclusive language.”

New Git Repos

New Repos will inherit from a policy that set the default branch name for new Repos.

This policy is set at the different levels:

  1. The Organization level under “Organization Settings” -> “Repositories”
  2. or at the Project level under “Project Settings” -> “Repositories” -> “Settings”
New Git Repos

Existing Repos

I will share here few commands to set your Azure DevOps default branch. There is a popular way to do that through Git cmdlet by renaming the master branch, I will share here another approach which consist in creating a new branch and locking the old one through Azure DevOps CLI extension.

In order to proceed you will need the following prerequisites :

Set up variables

Since these variables are re-used, a locals block makes this more maintainable.

organization=”https://dev.azure.com/organization_name/"targetBranch=”main”

Connection

Connect directly through Azure AD or use a Personal Access Token that has the minimum privileges :

  • Read privilege a the Projet and Team level.
  • Full privilege at the Code level.
az login# ORaz devops login

Script & Workflow

  1. List all our Azure DevOps projects
  2. List our Azure DevOps repositories
  3. List our ref to determine the current default branch
  4. Create the new ref if it doesn’t exist
  5. Update the repo with the new default branch
  6. Lock the old default branch
New Default Branch

The script →

https://gist.github.com/JamesDLD/fc15dd24971f9e18ee0ac84ddea2e0fe#file-az_default_branch-sh

#!/bin/bash
# ------------------------------------------------------------------
#            Set Azure DevOps Default Branch on All Repo
#                 If branch doesn't exist it will 
#            create it from the current default branch
#              previous default branch will be locked
#Ref : https://devblogs.microsoft.com/devops/azure-repos-default-branch-name/
# ------------------------------------------------------------------

#Variable
set -e #stop on error
organization="https://dev.azure.com/YourOrganizationName/"
targetBranch="main"
iteration=1

#Ensuring that az and jq cmdlet are available
if [ $(which az) ] && [ $(which jq) ] ; then 
    echo "az and jq are available"
else 
    echo "az or jq are not not available"
    exit 1
fi

#Ensure that the Azure DevOps extension is installed https://docs.microsoft.com/en-us/azure/devops/cli/?view=azure-devops
if az extension show --name azure-devops ; then 
    echo "The Azure DevOps CLI extension is installed"
else
    echo "Installing the Azure DevOps CLI extension"
     az extension add --name azure-devops
fi

#Connect with Azure AD
#az login

#list ADO projects
if projects=$(az devops project list --organization $organization | jq -r '.value[] | @base64') ; then 
    echo "az login authentication worked"
else
    echo "az login authentication didn't worked, fill in your PAT using those minimum privileges : Projet and Team = read & Code = Full"
    az devops login
fi
echo ""

for project in $projects; do
    _jqproject() {
     echo ${project} | base64 --decode | jq -r ${1}
    }
    project_name=$(_jqproject '.name')
    project_id=$(_jqproject '.id')
    echo "[$iteration] Working in project $project_name having the Id $project_id"

    #list ADO repos
    repos=$(az repos list --organization $organization --project $project_id | jq -r '.[] | @base64')
    for repo in $repos; do
        _jqrepo() {
        echo ${repo} | base64 --decode | jq -r ${1}
        }
        repo_defaultBranch=$(_jqrepo '.defaultBranch')
        repo_id=$(_jqrepo '.id')
        repo_name=$(_jqrepo '.name')
        echo "[$iteration] Repo $repo_name with id $repo_id has the default branch $repo_defaultBranch"

        if [ $repo_defaultBranch != "refs/heads/$targetBranch" ] && [ "$repo_defaultBranch" != "null" ] ; then 

            refs=$(az repos ref list --organization $organization --project $project_id --repository $repo_id | jq -r '.[].name')
            if [[ "$refs" == *"refs/heads/$targetBranch"* ]] ; then 
                echo "[$iteration] Ref refs/heads/$targetBranch already exist on repo $repo_name having the id $repo_id"
            else
                echo "[$iteration] Creating ref refs/heads/$targetBranch on repo $repo_name having the id $repo_id"
                refFrom=$(az repos ref list --organization $organization --project $project_id --repository $repo_id | jq -r '.[] | select( .name == "'"$repo_defaultBranch"'" ) | .objectId')
                az repos ref create --name "heads/$targetBranch" --object-id $refFrom --organization $organization --project $project_id --repository $repo_id
            fi

            echo "[$iteration] Setting the refs/heads/$targetBranch as default branch of repo $repo_name having the id $repo_id"
            az repos update --organization $organization --project $project_id --repository $repo_id --default-branch "refs/heads/$targetBranch"

            echo "[$iteration] Locking the $repo_defaultBranch of repo $repo_name having the id $repo_id"
            az repos ref lock --organization $organization --project $project_id --repository $repo_id --name "$(echo $repo_defaultBranch | cut -c 6-)"

        else 
            echo "[$iteration] Default branch ok for repo $repo_name having the id $repo_id"
        fi
        iteration=$((iteration+1))
        #exit;
        echo ""
    done
    echo ""
    #exit;
done

Conclusion

Changing a default Git branch might not be as simple as mentioned in the upper chapter, some additional steps might be needed in specific context like when the default branch is used to publish application or when application are directly plugged in your default branch.

Those are some recommendations that I used to share :

  1. Use the same default branch name for all your repos.
  2. Fit with global rules. I would say that when the Git project define a default branch name, it’s a global rule. So I will use main as default branch.
  3. Use a custom branch to publish into production.

I hope you enjoyed the article.

See You in the Cloud.

Jamesdld

For more great content, check out the Resource Centre

About the Author:

I am specialized in building IT Infrastructures with a DevOps Architect mindset. I am fascinated by technologies that make IT Infrastructures easy to use, deploy and evolve.

Reference:

le Douarec, J. (2020). Set the default branch on your Azure DevOps Repos. Available at: https://faun.pub/set-the-default-branch-on-your-azure-devops-repos-e929b97de112 [Accessed: 16th May 2021].

Share this on...

Rate this Post:

Share:

Topics:

Azure

Tags: