Question: How to solve a merge conflict with a zillion of JSON files?
How to unfuck this clusterfuck?
Someone had to create a clean branch containing JSON files, after two cherry-picks they suddenly had merge conflicts and over 180 files which were changed. Chaos and panic! The problem was, most of the files were JSON files. The order of keys might change because of randomness… So how do you fix this problem?
Answer
If the files are automatically generated it could be an easy solve. In the rebase (or cherry-pick) accept the other sides changes, than run the regeneration and commit that solution. You done and can stop reading this answer.
But for all intent and purposes, this wasn’t the case for that person.
My best guess was or is, the JSON wasn’t canonicalized. So you need to fix that
first. It makes diffing and fixing the merge conflict much and much easier to
think about. My go to tool is json_xs, but you need to install
JSON::XS, which is a perl module: cpanm JSON::XS, thank me later.
You can than use this script, which I call pretty-json, to normalize/canonicalize the JSON:
#!/usr/bin/env zsh
for i in $@ ; do
res=$(json_xs -t json-pretty < $i)
rv=$?
if [ $rv -eq 0 ] ; then
print -r "$res" > $i
continue
fi
exit $rv
done
Now, you actually want do have this in each commit fixed and ordered.
So.. you need to know which JSON files are impacted from your old branch: git diff --name-only HEAD^3...HEAD. I say HEAD^3 because OP said its just three
commits, adjust where needed.
Now you know which files you need to normalize on your current main branch.
# first bring sanity for our branching
git fetch origin
git checkout -b fix-the-glitch -t origin/master
# now bring sanity to json files
pretty-json a.json b.json c.json
git add a.json b.json c.json
git commit -m "Normalize JSON files for merge sanity" a.json b.json c.json
# now bring sanity in your MR branch
git checkout -b fix-glitch-from-mr origin/mr
# Now pick the files in each commit, and I prefer to use the commit-shas here
git checkout commit1 a.json
pretty-json a.json
git commit --fixup commit1 a.json
git checkout commit2 a.json
pretty-json a.json
git commit --fixup commit2 a.json
git checkout commit3 a.json
git commit --fixup commit3 a.json
# You need to do this for all the JSON files in all the commits,
git rebase --autosquash -i commit1^
Now you have a branch where you have normalized all the JSON and you can do the actual work:
git rebase -i fix-the-glitch
The JSON files are the hardest, because JSON moves things around and you have solved that. Once you fixed that, you can focus on the actual conflicts that are bubbling up. You’ll probably still see JSON differences, but they are MUCH easier to resolve.
And to make things easier for you and anyone else, you can add a
.gitattributes file in your repo:
*.json diff=json
and configure this in your gitconfig:
[diff "json"]
textconv = json_xs -t json-pretty