Azure DevOps merge types: squash, rebase, semi-linear and Limit merge types
When you complete a pull request, the Merge type decides what lands on the target branch. Azure Repos offers four, and a branch can allow only some of them with the branch policy Limit merge types; Azure DevOps then refuses a completion with any other type. Below is what each does and where the limits come from, from Microsoft's Complete a pull request and branch policies pages.
The four merge types
- Merge (no fast forward): a merge commit whose parents are the target and the source branch. The history stays non-linear and keeps every commit.
- Squash commit: one new commit on the target with all the changes. The source branch's commits are not kept, and the new commit has no reference to the branch, so Microsoft suggests deleting the source branch after a squash (Merge strategies and squash merge).
- Rebase and fast-forward: the source commits are replayed onto the target, with no merge commit.
- Semi-linear merge: the source commits are replayed onto the target, then a merge commit with two parents is added. Also called rebase and merge; the policy calls it "Rebase with merge commit".
Rebase and fast-forward and semi-linear merge came in 2019 (Sprint 150); before them there were only a merge commit and a squash. Azure DevOps Server takes the two newer types from Server 2019 Update 1; TFS 2018 and Server 2019 without the update merge or squash only.
Limit merge types
- By default every merge type is allowed. In the branch's policies, turn Limit merge types on and tick the ones to keep: Basic merge (no fast-forward), Squash merge, Rebase and fast-forward, Rebase with merge commit.
- Older policies said "squash merge only", and they are still enforced: to use another type on such a branch, edit the policy (Sprint 150, and the note in Complete a pull request).
- From the command line:
az repos policy merge-strategy createwith--allow-no-fast-forward,--allow-squash,--allow-rebaseand--allow-rebase-merge. The older--use-squash-merge("always squash merge") is deprecated. - Someone with permission to override branch policies sees Override branch policies and enable merge in the Complete pull request pane and can complete anyway.
The usual surprises
- The type you want is not there, or the completion is refused. The target branch limits merge types. Pick an allowed one, or ask whoever can edit the branch's policies.
- A rebase is not possible (Sprint 150): when a policy of the target branch prohibits the rebase types (you need permission to override branch policies), when the source branch has policies of its own (the rebase would change it without them), or after resolving conflicts with the Merge Conflicts extension. Rebase locally and push, or squash.
- az repos chooses only squash or not.
az repos pr updateandaz repos pr createtake--squashamong the completion options; the rebase types are not in that list. The REST API'scompletionOptions.mergeStrategytakes all four. - A squash leaves the branch looking unmerged. Its commits are not on the target, so Git does not see the branch as merged; delete it when you complete.
The merge commit message
- In the Complete pull request pane, the post-completion option Customize merge commit message lets you write the message of the merge commit yourself (Complete a pull request). Microsoft notes that some options are not offered for some merge types; Rebase and fast-forward adds no merge commit at all.
- From the command line,
az repos pr updateandaz repos pr createtake--merge-commit-messageamong the completion options, as they take--squash. - In the REST API it is
completionOptions.mergeCommitMessage, documented from version 4.1: "If set, this will be used as the commit message of the merge commit" (Pull Requests - Update). Its example sets it together with auto-complete, so a pull request that completes by itself takes the message too.
Merge types in IntelliJ IDEA
Azure DevOps Pull Requests, a plugin by Lesstep for JetBrains IDEs 2024.1 or later and Android Studio, lists the pull requests of Azure DevOps Services and Azure DevOps Server in an IDE tool window. Its Complete dialog has the four merge types (merge or squash on TFS 2018 and Server 2019 before Update 1) and, from version 1.0.53, only those the target branch allows, with the allowed types named among the branch policies. You can also set auto-complete with your merge type. From version 1.0.68 the dialog also has the merge commit message, for completing now and for auto-complete; left empty, Azure DevOps writes its own, and it is off for Rebase and fast-forward. The review inbox and the branch policies are free; voting, commenting, completing and creating pull requests are Pro, with a 30-day trial.
Get it on JetBrains Marketplace
Azure DevOps is a trademark of Microsoft Corporation; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with or endorsed by Microsoft or JetBrains.
More: merge conflicts and the Merge Conflict extension · auto-complete and optional policies · required reviewers and path filters · explicit override to bypass policies · why an approval does not count · Azure DevOps pull request plugins for IntelliJ IDEA, compared · 日本語