In general, it is quite difficult.
Some have tried to use the Git union merge (which is now more accessible than at the beginning, as in this question you just add merge=union in the .gitattributes file), but that doesn't work at all. This can sometimes work. This is very important if your XML is always structured so that the naive linearly-oriented union merge produces the correct XML (basically, keeping all sub-elements of the whole XML in one line), and you always add a whole new XML element.
In Git, it is possible to create a custom merge driver. Writing useful for XML is difficult.
First we need an XML diff engine, such as Sylvain Thénault xmldiff , to build two lines per line (or from tree to -tree) for three XML files (merge base, local or --ours and other or --theirs files: diff base- vs-local and base-vs-ours). This particular one looks like it works similar to Python difflib . (However, due to the referenced documents, it looks like it does tree movement / tree nesting operations, as well as simple insertions and deletions. This is a natural and reasonable thing for a tree-tree editing algorithm, and perhaps really desirable here. )
Then, given these two differences, we need code to combine them. The union method should ignore all deletions: just add all additions to the base version (or, equivalently, add "other" additions to "local" or "local" additions to "other"). We could also combine tree insertion / deletion operations a la "real" (non-union-style) and possibly even declare conflicts. (And it would be nice to allow different handling of changes in the level of nesting of the tree, driven by something vague, like DTD.)
These last parts, as far as I know, are still not done anywhere. Also, the Python xmldiff bundled here is a pretty large piece of code (I haven’t read it anywhere close, and I haven’t tried to install it, I just downloaded it and removed it - it implements both Myers-like algorithm and fancier "fast match / edit script "from Stanford paper ).