Salesforce, Python, SQL, & other ways to put your data where you need it

Need event music? 🎸

Live and recorded jazz, pop, and meditative music for your virtual conference / Zoom wedding / yoga class / private party with quality sound and a smooth technical experience

Protecting Git branches in Azure DevOps repositories

10 Mar 2023 🔖 devops git azure
💬 EN

Table of Contents

Before – or instantly after – you first store any given codebase (like a tiny webserver) in Azure DevOps (“ADO”) Repositories (“repos”), I recommend protecting certain branches like “main,” protecting them from being directly edited.

It’s considered best practice, when more than 1 developer is working on a project, to refrain from committing directly to any long-lived branch.

Instead, you should “branch” a smaller branch off of the one you really want to edit, edit that one, and then open and close a “pull request” of your work back into the branch you really want to edit.

Enforcing this best practice is something that you set up within the configuration parameters of git-tracked codebase-hosting websites like Github, BigBucket, GitLab, AWS CodeCommit, or Azure DevOps, not something built into the git protocol itself.

Today I’ll teach you how to protect your branches from direct updates in ADO Repositories.

Why you should do this immediately

Even if you’re a solo developer today, if you’re using Azure DevOps instead of a free-without-a-credit-card platform like GitHub to host your git-tracked code, you’re probably working for a larger company.

Force yourself to use pull requests and comment on and approve your own pull requests, for practice.

One day you’ll have teammates, or hire a consultant, and you’ll be glad you learned your way around ADO’s pull request user interface.


Branch policies vs. locking

The “branch policies” I’ll cover first enforce “quality of teamwork” business processes that help you be neat and tidy (before ADO will let you merge a pull request into a given branch).

However, ADO “branch policies” don’t force you to use pull requests in the first place, rather than just doing a git commit and git push directly onto the branch in question (or rather than directly editing code for the branch in question using ADO’s point-and-click code-editor user interface).

Only “locking” a branch forces you to use a pull request from another branch (rather than making a direct git push or direct edit onto a branch) to update the contents of the “locked” branch.

Update: I might be wrong about this.

  • I swear I was getting direct-edits to main through on repositories when I had “branch policy” settings toggled on project-wide a month ago.
  • But today ADO was yelling at me even without me bothering to toggle locks onto main as I proofread this exercise and this one, so maybe locking is redundant and “branch policies” do the trick alone.
  • Locking doesn’t doesn’t seem to hurt, though, so I suppose you might as well also lock branches you care about, just in case.

In fact, you can “lock” a branch without having any “branch policies” on it at all.

In that case, the “branch policies” for it would implicitly be the same as if you’d manually toggled all of the policy settings to “off.”

However, you probably won’t find that you enjoy using pull requests very much until you think about the “quality of teamwork” business processes you’d like to enforce with “branch policies.”

I’ll cover the “how-to” of “branch policies” before “locking” because you can, as a good habit, set certain branch policies ADO-project-wide before you’ve even created a single repository in the project.

(Whereas you can’t actually “lock” a branch within a repo until it exists, which might be weeks or years later.)


Branch policies

Set project-wide default branch policies

If you’d like, you can pre-set branch policies for all branches tagged “Default” that anyone ever creates in any repo of your ADO project.

You can even do this before you’ve created a single repository!

  1. Visit the “Cross-Repository policies for default branch” page at https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_settings/repositories?_a=policies&refs=~default, of course substituting appropriate values for YOUR-ADO-ORG-NAME AND YOUR-ADO-PROJECT-NAME.
  2. In the “Branch Policies” section, toggle on “Require a minimum number of reviewers.”
  3. If you’re just getting started with a single developer who’s tasked with initial setup for everyone else:
    • Change “Minimum number of reviewers” to 1.
    • Check “Allow requestors to review their own changes.”
    • Leave “Prohibit the most recent pusher from approving their own changes” unchecked.
    • Leave “When new changes are pushed unchecked because when you select one of its sub-options like “Require at least one approval on the last iteration,” Azure DevOps behaves buggily and completely ignores your choice above to “Allow requestors to approve their own changes.”
  4. In the “Branch Policies” section, toggle on “Check for linked work items.”
    • If you haven’t bothered getting ADO Boards going yet in your team, select the “Optional” radio button.
  5. In the “Branch Policies” section, toggle on “Check for comment resolution” and select the “Required” radio button.

IMPORTANT: Once you’ve got a whole team working together, come back and edit these settings to be more appropriate to the way you’ll actually work for the next several years.

Settings auto-save as you click them; feel free to navigate away from the page any time you’re done.

WARNING: These settings will not actually do anything meaningful to any branch of any repository until you lock the branch that’s tagged as the repository’s default branch.

Wait to lock your default branch until you’ve done the first import of legacy code into your repository, or until made your first code commit into that default branch of a brand new empty repository. Otherwise, you won’t be able to get any code into the repository at all and it will remain empty forever.

(It should be pretty easy to avoid accidentally locking the branch too early. There won’t be a place to find a “lock” settings for a main, master, etc. branch – because there won’t be such a branch at all – until you’ve direct-point-and-click-edited, committed+pushed, or imported some code into the formerly-empty repository.)

Set other project-wide known-branch-name policies

If you’d like, you could also pre-set branch policies for all branches named BRANCH-NAME-HERE that anyone ever creates in any repo of your ADO project.

(Maybe you’d like to do so for “dev,” for example.)

  1. Visit the “Cross-Repository policies for BRANCH-NAME-HERE” page at https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_settings/repositories?_a=policies&refs=BRANCH-NAME-HERE, of course substituting appropriate values for YOUR-ADO-ORG-NAME AND YOUR-ADO-PROJECT-NAME and BRANCH-NAME-HERE.
  2. Repeat the steps above as you see fit for your team.

Tip: I don’t bother to do this manually for the names “main” or “master” – I just make sure ADO has each repo’s main / master branch marked as its repository’s “Default” branch.

ADO is usually pretty smart about assigning a “Default” tag automatically, but I always double-check in each repository’s “Branches” page at https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_git/YOUR-REPOSITORY-NAME/branches once at least one branch exists.

(Brand new empty repositories don’t have branches.)

Settings auto-save as you click them; feel free to navigate away from the page any time you’re done.

WARNING: These settings will not actually do anything meaningful to any branch called BRANCH-NAME-HERE within any repository until you lock the branch by that name within the repository in question.

Set per-branch per-repository policies

If you’d like, you can repeat your steps to set branch policies for a specific “BRANCH-NAME-HERE” branch within a specific “YOUR-REPOSITORY-NAME” repository.

  1. Visit the “Branches” page at https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_git/YOUR-REPOSITORY-NAME/branches.
  2. Click on the 3 vertical dot icon that appears (when you hover over the name of the branch) at the far right side of the screen for whichever branch you’d like to set some policies for.
  3. Click “Branch policies”.

If the branch is one you’ve never set any ADO-project-wide settings for, the screen will look a lot like the ADO-project-wide branch policy editor pages.

If the branch whose policies you’re setting are also covered by one of the ADO-project-wide settings for “default” or “branch-named-BRANCH-NAME-HERE” branches, you might find that you’re allowed to toggle/untoggle/check/uncheck/edit some fields but not others. You’ll see the user interface warn you about “Inheritance” and offer a link to let you know which project-wide policies the branch is already inheriting settings from.

Settings auto-save as you click them; feel free to navigate away from the page any time you’re done.

WARNING: These settings will not actually do anything meaningful to the branch until you also lock it.


Locking branches

WARNING: None of your “branch policies” settings above will actually do anything meaningful until you lock the branch you’re trying to protect within the repository in question.

To lock the branch that’s tagged as the YOUR-REPOSITORY-NAME repository’s default branch:

  1. Visit the “Branches” page at https://dev.azure.com/YOUR-ADO-ORG-NAME/YOUR-ADO-PROJECT-NAME/_git/YOUR-REPOSITORY-NAME/branches.
  2. Click on the 3 vertical dot icon that appears (when you hover over the name of the branch) at the far right side of the screen for whichever branch is tagged “Default.”
  3. Click “Lock.”
  4. A padlock icon will appear to the right of the branch’s name and to the left of its “Default” tag.
  5. Your work has auto-saved; you can navigate away from the page now.

You can, of course, do this for other branches as well.

For example, maybe you’d like to lock down a long-running dev branch from direct edits and force people to use pull requests to edit its content as well.


Posts in this series

--- ---