https://github.com/kodybrown/sortxml
You may be able to write a small wrapper script that does the following: For each filename passed as argument to your script you will run sortxml on it and store the result in a temporary file, then once you've done so for all files, you pass the sorted files to an existing merge tool such as for example meld, kdiff3 or vimdiff.
Let's say that you name your script mergexml.bash and that you put it in ~/bin/. Then it should be possible to first git merge as usual but when a conflict arises in an XML file, you will run something like
git mergetool -t ~/bin/mergexml.bash example.xml
And your script will have simplified the process.For bonus points, you might write an unsortxml program that your script will call at the end to rearrange the nodes and attributes to be in the same order as they were in one of the original XML files -- the user would be prompted to select which of the original XML files to use for ordering the nodes and attributes.
I haven't tested this of course, otherwise I'd probably have actual code to share for it but I think something like what I've outlined above should work.
mkdir -p ~/tmp/xml-merge-example
cd !$
git init .
cat > example.xml <<EOF
<?xml version='1.0'?>
<hurr durr='hello'/>
<durr hurr='world'/>
EOF
git add .
git commit -m "Initial commit."
git checkout -b alternate-reality
cat > example.xml <<EOF
<?xml version='1.0'?>
<durr hurr='world'/>
<hurr durr='hello'/>
<foo reality='alternate'/>
EOF
git add .
git commit -m "Alternate reality."
git checkout master
sed -i '' -e 's/hello/foo/' -e 's/world/bar/' example.xml
git add .
git commit -m "Hello foo to the world bar."
git merge alternate-reality
The attempted merge will result in the following: Auto-merging example.xml
CONFLICT (content): Merge conflict in example.xml
Automatic merge failed; fix conflicts and then commit the result.
For a quick PoC, let's create a little script that will echo the arguments that was passed to it and then exit with failure. The real script would work as outlined in the parent comment and would exit with success at the end as long as the merge worked out.The t argument to mergetool works a bit different than I thought, but not by much -- the tool must be referenced by name and the corresponding mergetool.<tool>.cmd must have been set. In the command you use the variables $BASE, $LOCAL, $REMOTE and $MERGED as explained in https://git-scm.com/docs/git-mergetool#git-mergetool--tlttoo... . This allows tools with different argument ordering, flags and such to be used.
Let's write the PoC script
mkdir -p ~/bin
cat >~/bin/mergepoc.bash <<'EOF'
#!/usr/bin/env bash
echo "$0: WARN: Proof-of-Concept" 1>&2
echo "$0: INFO: Arguments: $@" 1>&2
exit 1
EOF
chmod 755 ~/bin/mergepoc.bash
and define the mergetool cmd git config mergetool.mergepoc.cmd '~/bin/mergepoc.bash --base "$BASE" "$LOCAL" "$REMOTE" -o "$MERGED"'
and tell git to trust the exit status of this tool git config mergetool.mergepoc.trustExitCode true
Then we run it. git mergetool -t mergepoc example.xml
Result (with an additional line-break inserted in order for to avoid having the contents shown here scroll sideways): Merging:
example.xml
Normal merge conflict for 'example.xml':
{local}: modified file
{remote}: modified file
/home/erikn/bin/mergepoc.bash: WARN: Proof-of-Concept
/home/erikn/bin/mergepoc.bash: INFO: Arguments: --base ./example_BASE_4020.xml
./example_LOCAL_4020.xml ./example_REMOTE_4020.xml -o example.xml
merge of example.xml failed
Continue merging other unresolved paths [y/n]? nAside: the conflicts mentioned in the article should never be a real problem because you can always resolve the conflict by just recreating the dependences.tsv file (you should never be editing it manually anyway).