Azure DevOps is not a second-class citizen

Introduction

The amount of FUD surrounding Azure DevOps and DevOps Server is staggering and perpetuated by rumors, opinions, half-truths, misunderstandings, and even lies. Microsoft has explicitly moved Azure DevOps Server (like Azure DevOps) to the Modern Lifecycle Policy and has a clear path for Azure DevOps.

  • Previously, on-premises versions had fixed “end of life” dates. Under the Modern Policy (updated late 2025/early 2026), it now receives continuous updates, signaling it is a permanent part of the Microsoft portfolio.
  • Reference: Microsoft Lifecycle Policy for Azure DevOps Server (Confirmed active through 2026 and beyond).
  • Azure DevOps has a timeline of support and evolution for modern needs in the Azure DevOps Roadmap: https://learn.microsoft.com/en-us/azure/devops/release-notes/features-timeline. We will focus on this in this document.

While for some GitHub fanboys this might seem painful, for some anti-Microsoft people, GitHub is even evil itself, so there is that. Ultimately, I use both.

Major New 2026 Feature: “Managed DevOps Pools”

Microsoft just launched (and is expanding in early 2026) a massive infrastructure feature called Managed DevOps Pools. Managed DevOps Pools documentation – Azure DevOps | Microsoft Learn

  • This is a heavy-duty investment specifically for Azure Pipelines. It allows enterprises to run pipeline agents on Azure with 90% cost savings via “Spot VMs” and custom startup scripts.
  • This matters because a company doesn’t build a massive new infrastructure scaling engine for a product they plan to dump. This is a direct investment in the future of Azure Pipelines.

Parity with GitHub Security (GHAS)

Rather than telling ADO users to move to GitHub for security, Microsoft brought the security to them.

  • GitHub Advanced Security (GHAS) for Azure DevOps is now generally available (as of late 2025/2026). It includes CodeQL-powered scanning and secret detection, natively integrated into the Azure DevOps UI.
  • Reference: Azure DevOps Release Notes – Sprint 250+ Update.

AI Integration (Copilot for ADO)

Azure DevOps is gaining native AI capabilities.

Summary Table

Evidence TypeDetailStatus (2026)
New VersionAzure DevOps Server 2022 Update 2 / 2025 RCReleased/Active
Major InfraManaged DevOps Pools (Scaling for Pipelines)Generally Available
SecuritySecret/Code Scanning natively in ADOActive Support
AICopilot for Azure Boards & MCP ServerRolling Out

Conclusion

The claim that GitHub is “replacing” Azure DevOps is incorrect. Microsoft is maintaining two distinct tracks:

  1. GitHub: The “Open-Source/Community” DNA or lifestyle.
  2. Azure DevOps: The “Enterprise/Compliance” DNA or lifestyle.

Microsoft is even bundling them—granting GitHub Enterprise customers Azure DevOps Basic access for free, recognizing that many companies use both simultaneously. In reality, both products influence each other as they evolve and modernize.

FeatureOriginally from…Now Influencing…
YAML PipelinesAzure DevOpsGitHub Actions (Standardized the YAML format)
Secret ScanningGitHubAzure DevOps (via GHAS for ADO)
Pull Request FlowGitHubAzure DevOps (Redesigned ADO PRs to match GH style)
TraceabilityAzure DevOpsGitHub Projects (Attempting to match Boards’ depth)

When an enterprise focuses on structured agile & compliance, well-defined, regulated processes, and heavily regulated deployments, Azure DevOps is a natural fit. This is why it is used and integrated into the security models of many enterprises, long before other tools entered the scene via freelancers (Jira, Confluence, GitHub), who now claim this is the way to go. In the end, that is pretty self-serving and disloyal. Sure, shortcomings in corporate processes might have reinforced such behaviors, but switching to those tools will not fix them.

Ultimately, Azure DevOps can both leverage and enhance GitHub in a corporate environment. Better together, where people can optimize tooling for their needs while maintaining compliance.

Addendum

Industry-Leading Project Management (Azure Boards)

For many enterprises, Azure Boards is the primary reason they stay.

Deep Traceability: In ADO, you can link a single line of code to a Pull Request, which is linked to a Build, which is linked to a Release, which is linked to an original “Feature” or “User Story.” This level of end-to-end auditing is required for regulated industries (Finance, Healthcare, Government) and is far more advanced than GitHub Projects. For example: the GitHub-to-Azure Boards connector. A developer in a GitHub Repo can now use a # command in a commit message that not only links to a Jira ticket but also triggers a state change in an Azure Board and a deployment in Azure Pipelines simultaneously.

Scale: Azure Boards can handle tens of thousands of work items across hundreds of teams with hierarchical parent/child relationships that don’t “break” at scale.

Specialized Testing (Azure Test Plans)

This is arguably the “killer app” for enterprise QA.

Manual & Exploratory Testing: GitHub essentially assumes you are doing 100% automated testing. Azure DevOps includes Azure Test Plans, a dedicated tool for manual testing, screen recording of bugs, and “Step-by-Step” execution tracking.

Quality Assurance Evidence: For companies that need to prove to auditors that a human actually tested the software before it went to AWS, ADO generates the necessary “proof” automatically.

Granular Permissions & Governance

Security Scoping: Azure DevOps allows you to set permissions at the Area Path or Iteration level. You can allow Team A to see “Project Alpha” but completely hide “Project Beta” within the same organization. GitHub’s permission model is flatter and often requires more complex “Team” management to achieve the same result. This is a great capability to have, no matter which hyperscaler you target.

Centralized Service Connections: In ADO, you define a connection to AWS once at the project level. In GitHub, you often have to manage secrets or OIDC trusts per repository, which creates a massive management burden for IT teams with 500+ repositories.

Clear the Git commits and history from the local & remote master repository

Introduction

Why would we clear the Git commits and history from the local & remote master repository? When preparing training labs leveraging Azure DevOps and Git, I often need to do a lot of testing and experimenting to empirically get the scenarios right. That means the commit history is cluttered with irrelevant commits for the lab training I am presenting.

Clearing the Git commits and history from the local & remote master repository
Photo by Gabriel Heinzer on Unsplash

Ideally, I reset the history to start a training lab when the repository is at the right stage. The students are then not bothered by the commits of previous demos. But how can we clear the Git commits and history from the local & remote master repository?

Clear the Git commits and history from the local & remote master repository

Git is meant to keep the commit history, as are repositories like Azure DevOps. That means there is no way to reset the commit history in Azure DevOps. Git, being a very powerful and, to a certain extent, also a dangerous tool, can help you overcome this. But how to do it is not always obvious. That said, you can also shoot yourself in the foot with Git, so pay attention and be careful.

Step 1 to Clear the Git commits and history from the local & remote master repository

If you keep branches around things get complicated. For my needs, I don’t need them. To delete a branch via git we need three (3) deletes.

git push origin --delete marshipdev
git branch --delete marshipdev
git branch --delete --remotes origin/marshipdev

The above lines respectively delete:

  • The remote branch in Azure DevOps
  • The local branch
  • The local remote tracking branch

You can also delete remote branches in Azure DevOps via the GUI by selecting a branch and selecting “Delete branch” in the menu. Locally you’ll need to use Git commands or the Git GUI.

Clear the Git commits and history from the local & remote master repository

Step 2

Create a new orphaned branch

git checkout --orphan myresetbranch

The Git option –orphan creates a branch that is in a git init “like” state. That is why we have an alternative option and that is to delete the .git folder in your local repository and run git init in it. That is why i normally keep a copy around of the “perfect” situation with the .git folder removed. I can copy that to create a new local master branch by running git init. I then have that track a new remote repository that still needs initializing via:

git remote add origin  https://[email protected]/workinghardinit/InfraAsCode/_git/AzureFwChildPolMarShip


git push --set-upstream origin master

But that is not what I am doing here, I am using another method.

Step 3

On your workstation in the local repository, make sure to clean and delete or edit and add all the files and folders we want to be in our master repository initial commit.

git add -A

git commit -m “Initial commit”

Note: we use -A here instead of  “.” Because we also want to delete any tracked files and folder that are currently being tracked. At the same time, it adds new items to be tracked. In practice it is like running both git -u and git .

Step 4

Now delete the current master branch

git branch -D master

Step 5

Rename the temporary branch to “master”

git branch -m master

We now have a master repository again locally.

Step 6

We now need to update the remote repository with the option –force or -f. That allows us to delete branches and tags as well as rewrite the history. Normally that is no allowed so we nee to temporarily allow this in Azure DevOps.

Clear the Git commits and history from the local & remote master repository

Now we can run

git push -f origin master

If we had not allowed Force push the above command would fail with an error indicating we need to allow “Force push”.
TF401027: You need the Git ‘ForcePush’ permission to perform this action.

Important: do not forget to set “Force push” back to “Not set”

Step 7 to Clear the Git commits and history from the local & remote master repository

Finally, make sure that the local master branch is set up to track origin/master.

git push --set-upstream origin master

That’s it, you now have a master repository in Azure DevOps that is ready to be cloned and used for labs with a clean commit history. Student can clone it, create branches, work on that repository and they will only see their changes and commit.

Conclusion

Resetting the git commit history of a repository is not a recommend action on production repositories under normal situations. But in situations like training lab repositories, it gives me a clean commit history to start my demos from.

Project Bicep, an ARM Domain-Specific Language

Project Bicep

Project Bicep? Biceps? Do you mean like bicep curls? Muscles? What does this have to do with ARM or ARM templates? Well, to master ARM templates, we can use a little extra power. So, It’s a joke so bad it’s good as Microsoft’s Alex Frankel put it.

Impressive power but not the kind of biceps we are talking about (image by Eduardo Romero on Pexels.com)

Over the years, I have noticed a couple of challenges when it comes to Infrastructure as Code (IaC). It is not an easy thing to achieve in practice. Not only in the cloud but anywhere. It is a significant hurdle in achieving IaC. Maybe you have the same experiences.

Azure Infrastructure as Code

In Azure, one of the biggest challenges has been the learning curve when it comes to writing the JSON. JSON, the “human-readable” data interchange format that brings ARM and ARM templates to live. It isn’t something you pick up super quickly and turns out to be harder and harder to use when things become more complex and diverse.

Other challenges are related to managing the templates, getting pipelines set up reliably and consistently for all resources in Azure tenants, subscriptions, resource groups, etc. It is not something that I would call inviting and easy to do.

Then there are the real-world realities we need to handle. There is a ton of “stuff” out there where deployment, configuration, orchestration, and change happens in different ways. How does one onboard all that in an IaC process without too much risk of breaking things? Unfortunately, this is tedious and fragile.

We like Infrastructure as Code

For many people, the above is a bit discouraging. Don’t get me wrong. People see, understand, and like the idea of Infrastructure as Code. They just have a hard time getting there. There are all sorts of tools for various environments and needs. We have all at least heard and probably looked at Chef, Ansible, Puppet, or Terraform. There are many others still, but I just listed the ones that have been getting some serious attention over the last four years. Choosing one is losing the benefits of another. Using them all is an operational, skills, and management challenge. They all have their strengths and weaknesses. The main differences are whether they take a procedural, declarative, or an orchestral approach to getting the job done.

While orchestration is very popular, it does feel a bit like a failure, but that is “emotion”. Why? Well, because in the end, we cannot manage change very well and end up throwing everything away and replacing it with a new deployment that has the changes in there. Everything is a cow now that gets slaughtered and replaced when it doesn’t function as expected or needs to change. That works well for lightweight and fast implementations. It is somewhat painful when using this in more massive deployments. But still, when looking at the results and preventing configuration drift, it gets the job done.

But even the best tools have issues that can be best described as “death by a thousand cuts.” The concept is simple, but that doesn’t make it easy to do!

Microsoft has heard this feedback

We like Infrastructure as Code. We do find it too hard to do well, especially if that is not the bulk of your work, and you are not a guru at it like Stanislav Zhelyazkov.

When Microsoft asked on Twitter, “What do you think is a knowledge gap for traditional #ITPros when it comes to transitioning to the cloud” I replied, “The biggest skills hurdle is related to IaC. ARM is tedious and hard to learn for many, yet a cornerstone … Fix that, and we can move 10 faster in any cloud journey.”.

Project Bicep
My honest reply to Microsoft’s Anna Chu

The above is not new feedback, far from. But recently (Build 2020) they talked publically about what they are doing about it if I recall correctly. Yes, Microsoft is addressing this challenge. Just last week I saw Project Bicep go public on Github!

So what is project Bicep?

Bicep is a project Microsoft announced at Build 2020 (May). It delivers what Microsoft calls Transparent Abstraction over Azure ARM and ARM templates.  ARM ==> Bicep get the joke? Ok, never mind, it is terrible to search for, however. You get a lot of irrelevant hits.

It has a couple of goals as you can learn from the video.

  • Human friendly, so readability and comprehensibility are essential. You have to be able to understand what you read and write without much effort.
  • What you write will create or compile JSON for you. Microsoft now seems to like “Transpiles” for this. Where earlier the sort of made the analogy of JSON being some sort of the Intermediate Language (IL) of IaC.
  • If you think of JSON of an IL (as MSFT suggests), it is easy to see that, just like with .NET, you might see different languages use to achieve the same goal. But for now, that is not the goal. The goal is to get a working, functional declarative language that is suitable for all kinds of users. We’ll see where this ends up.
  • It focuses on modularity, so no, it will not create giant ARM templates, but modular ones. That means there is multi-file support.
  • It should evolve at the speed of Azure, so no waiting for six months to get new functionality implemented. Microsoft calls this “transparent abstraction.”
  • They plan a migration/conversion/export tool for existing ARM JSON!

Read up on project Bicep over here https://github.com/Azure/bicep. It clarifies the current state of what Bicep is and is not. I hope this moves fast and delivers better tooling to make Infrastructure as Code a better, more accessible, and more achievable goal for all of us.

WARNING

Bicep is at a super early stage of its existence. This is the earliest Alpha you can imagine. It is going to break, barf, and probably puke on your Azure stuff once in a while. So please, DO NOT USE THIS IN PRODUCTION. Right now it is only to get a feel for it, tinker around and get some feedback. This is you only and final warning.

In all honesty, it is very raw and as a (non-Linux) hardcore dev, this is not love at first sight for me, as I had hoped to use PowerShell for this. I hope it will mature and I will grow to love it and like using it much more than ARM. Anyway, dive into the bicep tutorial to see what you think.