{
  "$type": "site.standard.document",
  "canonicalUrl": "https://johnnyreilly.com/posts/azure-devops-pull-requests-conventional-commits",
  "description": "How to merge a pull request in Azure DevOps and maintain a git commit history of conventional commits, using the Azure DevOps API and build validations.",
  "path": "/posts/azure-devops-pull-requests-conventional-commits",
  "publishedAt": "2025-08-29T00:00:00.000Z",
  "site": "at://did:plc:yy3apqjlms24kso7ahn7lbmb/site.standard.publication/3mova7c4nho2b",
  "tags": [
    "typescript",
    "azure devops",
    "node.js"
  ],
  "textContent": "There was a time in my life when I didn't really care about commit messages. I would just write whatever I felt like, and it was fine. Over time, I learned that good commit messages are important for understanding the history of a project, especially when working in a team. And also, because I tend to forget what I've been working on surprisingly quickly.\n\nThere's also more technical reasons to care about commit messages. For example, if you're using a tool like semantic-release to automate your release process, it relies on conventional commit messages to determine the next version number and generate release notes. It turns out that Azure DevOps has some challenges when it comes to maintaining a git commit history of conventional commits, especially when merging pull requests. By default, Azure DevOps uses a commit strategy that creates a merge commit with a message like \"Merge PR 123: Title of pull request\". This is acts against conventional commits.\n\nYou can use the UI to change the commit message when completing a pull request, but it's very easy to forget to do this. And if you're using squash merges, you lose the individual commit messages from the feature branch, which can be a problem if you're trying to maintain a history of conventional commits.\n\nThere is a way to bend Azure DevOps to our will; to allow us to control our commit messages. In this post, I'll show you how to do just that using the Azure DevOps API, some TypeScript and build validations. The fact this mechanism lives in a build validation means you cannot forget to set the commit message. That's the feature.\n\nThis post is not, in fact, specifically about using conventional commits. That's just a common use case. Rather this post is about being able to control the commit message when merging pull requests in Azure DevOps.\n\n\n\nThe approach\n\nThe internet has been angry about Azure DevOps pull request commit messages for a while. There are feature requests which have been open since 2018 and Stack Overflow questions on the topic.\n\nAzure DevOps very rarely gets new features these days, and so it's unlikely that we'll see any changes here. However, there is one avenue that is open to us. Azure DevOps has the ability for a pull request to be set to autocomplete, which means that it will automatically merge when all policies are satisfied. This is useful for ensuring that the pull request is merged without manual intervention once it meets the requirements. For example when build validations have passed, and the required reviewers have approved.\n\nI've written about merging pull requests and setting autocomplete with the Azure DevOps API previously. We're going to build on that knowledge here, but add in the magic of setting the merge commit message when we set the pull request to autocomplete. This is achieved by the pull requests API. It allows us to update a pull request and set it autocomplete with a specific message commit message.\n\nThis should allow us to go from commits like this:\n\nTo commits like this:\n\nI should say that I'm using conventional commits as my commit message style, but you can use whatever style you like. The important thing is that you have control over the commit message.\n\nThe code\n\nWe're going to write a script that can be run in a build validation pipeline. This script will set the pull request to autocomplete with a specific merge commit message. This means that if you use conventional commits, you'll get to maintain a history of conventional commits in your git history.\n\nBefore we dive into the full code, here's the bit that does the magic of setting the merge commit message when setting the pull request to autocomplete:\n\nHere we are:\n\n- Setting the autoCompleteSetBy property to the authenticated user. This is required when setting a pull request to autocomplete.\n- Setting the completionOptions.mergeStrategy to squash. You can change this to rebase or noFastForward if you prefer those strategies.\n- Setting the completionOptions.mergeCommitMessage. This is where we set our conventional commit message. Or if you wanted to use a different style, you could set it to whatever you like.\n\nThe full TypeScript script\n\nNow that we understand the principle, here's the full set-autocomplete-and-commit-message.ts script that you can use in your build validation pipeline:\n\nThis can also be run locally with node ./set-autocomplete-and-commit-message.ts --token [PAT TOKEN WITH SCOPES: vso.code_write and vso.identity] --pr-id [PULL_REQUEST_ID] --org [NAME_OF_ORGANISATION] --project [NAME_OF_PROJECT] --repo [NAME_OF_REPOSITORY]. You'll need Node.js 24 or later to run this. (And yes, you can run TypeScript files directly with Node.js these days).\n\nThe thing I haven't included here is how you determine the mergeCommitMessage. In my case, I use the title of the pull request as the commit message. You can fetch the pull request details using the Azure DevOps API and extract the title. I left this out for brevity, but you can easily add it in. Or use whatever logic you like to determine the commit message. The point is that you have control over it.\n\nThe build validation pipeline\n\nNow we have our script, we need to run it in a build validation pipeline. Here's an example of an Azure DevOps pipeline that runs the script:\n\nCrucially, this pipeline is triggered only for pull requests; the System.PullRequest.PullRequestId is only available in build validations run as part of a pull request. The pipeline installs Node.js 24 and then runs our script, passing in the necessary parameters. The System.AccessToken is used to authenticate with the Azure DevOps API, so make sure that the pipeline has the necessary permissions to use it.\n\nConclusion\n\nAnd that's it! With this setup, you can maintain a git commit history of conventional commits in Azure DevOps, even when merging pull requests. By using the Azure DevOps API to set the merge commit message when setting a pull request to autocomplete, you can ensure that your commit messages are meaningful and consistent.",
  "title": "Azure DevOps: merging pull requests with conventional commits"
}