Notes to Self

Alex Sokolsky's Notes on Computers and Programming

Custom Git Merge Driver

Problem statement: how to merge generated files, e.g., JSON?

how-to-write-a-custom-git-merge-driver

Mark Files as Generated

In .gitattributes assign an attribute linguist-generated to keep certain files from displaying in diffs by default.

releases/** linguist-generated
releases/manifest.json merge=json-manifest

Specify Merge Driver to Use

Change repo config in Makefile:

# This is the base directory for this repo
BASE_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))

...

# setup the various git configuration for this repo
.PHONY: setup
setup:
    git config merge.json-manifest.name "merge manifests.json"
    git config merge.json-manifest.driver "${BASE_DIR}scripts/json-manifest-merge.py %O %A %B"

Merge Driver Implementation

Finally, merge-json.py

'''
This is a git custom JSON merge driver.  It takes 3 args:
    - the "old" file
    - the "new" file
    - the "merged" file, where we should write the result.
We assume that the file is a JSON object that we can simply "merge" (.update)
'''
import sys
import json

if __name__ == '__main__':
    old_path, new_path, dest_path = sys.argv[1:]

    with open(old_path) as fh:
        old = json.load(fh)
    with open(new_path) as fh:
        new = json.load(fh)
    old.update(new)  # merge

    # write out the merged map
    with open(dest_path, 'w') as fh:
        fh.write(json.dumps(new, indent=4))