Merging concurrent changes in AX with TFS

Suppose you’re an AX developer working in an AX instance shared by few other developers. You want to do some changes that would likely cause issues to your colleagues until they’re finished, therefore you’ve created a separate instance and work there. To simplify the example, assume that you’ve changed only a single method.

If nobody changed it in the meantime, it’s all good – you can simply import the method. But if somebody changed it, importing your code is a bad thing, because you would overwrite somebody else’s code. It doesn’t mean just that a feature would disappear; you would probably remove only a part of a feature and the behavior of the remaining application would be unpredictable.

What you have to do is to merge your changes with the current version of the application. In the simplest case, you want to keep all changes, therefore you’ll add your changes to what’s already there. Sometimes you want to replace a previous change (because, for example, somebody made a quick fix before your more robust solution gets ready). Sometimes you’ll have to implement completely new code to allow concurrent changes to work together. In the worst case, the changes are not compatible and can’t be merged together at all. (This usually reveals a problem with project management.)

My experience indicate that the main problem is not that developers fail to merge code correctly – they often don’t do it at all and overwrite previous changes. Unfortunately you can’t avoid merging if you want to support parallel development on the same objects, nevertheless you CAN ensure that people don’t skip merging.

The answer is obviously a version control system. If you take an object from a repository, modify it and you’re going to commit it, the version control system checks whether there aren’t already conflicting changes. If there are any, you’re not allowed to continue without resolving conflicts.

Let’s take a look at a concrete example with a few pictures. I’m going to simulate two developers working on AX2012 with Team Foundation Server. Each developer has his own AX instance pointing to the same team project and branch.

To make it easier, I used a single instance and I simulated the other developer by adding some change directly in Visual Studio, using a different TFS workspace. I took an existing, empty job and checked it out to both workspaces. In Visual Studio, I typed in // Code added in Visual Studio and checked the change in. In Dynamics AX, my change was // Code added in AX. When committing changes, TFS detects a conflict and shows a dialog where you can see and merge changes:


This is a very simple example, nevertheless you can see that is shows the changes I’m checking in, the changes done by others in newer versions and the resulting merged code (on the bottom). If there are several conflicts, I can resolve them one by one or simply accept one of versions of the files: ResolveAll

I can change the code in the bottom pane as needed. For example, I decided to merge comments by creating a completely new one:


The code inserted to TFS is the result of this merge, of course:


You may not like that the dialog uses the format of .xpo files and not a visual tree as in AX, but that’s how AX code and metadata are saved to source control systems and it’s usually better for merging anyway. By the way, .NET code is stored and compared exactly in the same way – as text files; it just has prettier formats. Don’t be too afraid of the .xpo format – it’s simple and you’ll need it in a few other cases, such as when reviewing changes line by line with annotate:


It’s also worth mentioning that you may want to have a separate branch for each developer and merge code on branch-level rather than changeset-level. An advantage for merging is that it happens independently on AX, therefore you can use latest tools, regardless what version of TFS is integrated to AX. On the other hand, you usually want to integrate code together (and find any issues caused by that) as soon as possible, which is an argument against too many branches.