How to merge json files using git
For my startup bubble, I do a lot of work using json. I have a number of very large, frequently-changing json files checked into git.
This causes a fair amount of pain, because git’s merge algorithm doesn’t know how to interpret or preserve the json tree structure, so it reports conflicts for things such as adding different keys to the same parent object, which textually can look like a conflict but semantically isn’t, at least for my purposes.
It got to the point where I’d be coordinating with my teammate to make sure we didn’t touch the same json files at the same time. Since the big win with git is being able to skip that kind of coordination, I got fed up and wrote a custom driver for merging json files.
It requires coffee-script to use (although porting it to javascript should be as simple as dumping it into coffeescript.org’s converter). Installation instructions are in comments at the top of the file.
The way it works is it recursively walks the structure of the file we’re merging into ours, and checks that each value matches the value of our file. If the value differs, it looks at the ancestor file (the version from before the two branches diverged) to see whether our version or their version was changed… if our version matches the ancestor file, then it goes with their version, and visa-versa.
If neither our version nor their version matches the ancestor, it reports that as a conflict. It reports a conflict by replacing the node with an object that looks like this:
{ "CONFLICT": "<<<<<<<<>>>>>>>>", //this is to make conflicts easy to find "OURS": ...our version of the node... "THEIRS": ...their version of the node... "ANCESTOR": ...the ancestor version.... "PATH": a .-seperated list of keys, indicating where in the file we are }
Resolving the conflict is as simple as copying our version or their version and pasting it over the conflict object.
The final, merged version of the file is then pretty-printed (it should be pretty easy to modify the code if pretty-printing isn’t what you want). And you’re all set!