Skip to content


Branch configurations for X++ repositories can vary significantly depending on two factors: dev team preferences and the current phase of a Dynamics 365 Finance implementation. Use the team's preferred branching structure provided it meets the minimum branching criteria. If none such exists, this document recommends two possible approaches that have been validated on actual D365 Finance projects.


You will find that a few elements of the X++ development cycle differ from general application development. Keep the following items in mind as you consider how to structure your branches:

  • ERP systems are business-critical environments. Therefore, when designing your code management infrastructure, prioritize design elements that minimize both:
    • risk of major production issues and
    • the disaster recovery timeline when failures do occur.
  • Because of the complexity and interdependency of the standard system code, it's generally a good idea to perform automated and manual testing of all critical business processes after each code update. Since testing can take days to complete, plan for a branch to contain the in-test code for long spans of time during validation.
  • X++ Dev teams frequently focusing their collective attention on enhancing specific modules and areas of the product. So, merge conflicts arise often with X++. Mitigate conflicts with a branching strategy that both reduce the frequency of collisions and ease collision resolution.

Minimum Branching Criteria

Any X++ repo branching strategy should support, at a minimum:

  • The isolation of un-tested development code from unit-tested development code. Developers should be protected from teammates accidentally breaking any active development branch, and isolating untested code from in-development code is an ideal way to provide this protection.
  • The isolation of unit-tested in-development code from test-eligible code. A code change may pass unit testing, and the associated task may still not be ready for functional testing. So, X++ branching structure should clearly notate when a collection of changes is ready for functional testing.
  • The isolation of in-test code from production code. Keep in mind that the fundamental purpose of version control: protecting production environments from code changes that have not been validated.
  • Relatively long (1+ week) functional testing cycles. For details on why D365 Finance customizations take longer to validate, read Considerations.

Branch Policy Guidance

Below are some branch policy best practices we recommend regardless of which branching strategy you choose:

  • The live/production code branch should be locked to prevent direct editing; changes should only be made via merge from other branches.
  • Before functional testing begins, all code changes should be reviewed by at least one reviewer.

Option 1: Sequential Branches

Sequential branching is a branching approach where the branches mirror the phases of the development cycle as code progresses chronologically from active development to functional testing to the live production environment.

When a developer is ready for functional testing, they "promote" their code to the Testing branch, for functional validation. Once the changes associated with a work item pass validation, they are promoted to the Production branch. The production branch contains the code running on (or soon to be deployed to) the live environment.

Unlike a feature or release branching strategy, sequential branches are long-lived and active for the life of the systems they support. Below is an example of this branch structure along with the merge path between branches.

graph LR
    A(Dev) --> B(Test)
    B(Test) --> C(Prod)

Figure 1. Sequential branch structure and merge path.


Compared to other branching strategies, sequential branching is relatively easy to understand as it mirrors the functional stages of the development cycle. Once configured, sequential branching requires no extra branching, which can be a benefit when your team is large or inexperienced with feature branching. The simplified branching structure also usually makes it easier for code administrators to isolate bugs.


Often, for D365 Finance ISVs, X++ development naturally breaks into feature or release partitions; it is less common for D365 Finance customers. In such cases, sequential branching is not the best fit. For sequential branching to work optimally, two Tier 2 environments are preferred: a functional testing environment for code validation, and a production mirror environment deployment testing and production troubleshooting. Tier 2 environments are relatively expensive, so budget-sensitive projects may not prefer this approach. Lastly, because the branch names so closely reflect the environments they support, the relationship between the branches and the environments can be confusing. The below diagram helps clarify the relationship.

Image mapping Dev, Test, and Prod repo branches to Dev, Test, Production Mirror, and Production environments

Figure 2. Environment branch relationship and code flow. The build VM is not a user-facing environment and is only shown here for completeness.

Option 2: Feature Branches

Feature branching is a branching approach where new development and bug fixes are isolated to short-lived one-off branches based on the production code branch. The branch is created when feature development begins, and merged when testing is successfully completed. Any number of feature branches may exist at the same time in a project.

      branch develop
      checkout develop
      branch feature1
      checkout develop
      branch feature2
      checkout develop
      merge feature2
      checkout develop
      merge feature1
      checkout main
      merge develop

Figure 3: Feature branch example.


Feature branches work well in X++ development when work items are relatively small, as is often the case after the completion of a significant D365 Finance project. Feature branches are typically used for the development of one enhancement or bug fix. It is the best approach for encapsulating the changes associated with a single work item.


Use of feature branch can create merge conflicts when multiple developers commit to the same area of code at a high frequency. In such cases, shared dev branch is preferable. Feature branches are typically independent where each branch owner is responsible for keeping their branch in sync with other changes. So, there is a real risk of the code in a feature branch "drifting" from changes in other feature branches or the main branch. This drift can also increase the overall time required to resolve merge issues. Consider the discipline of your dev team as you investigate this option.