SOLVED Resolve merge conflicts



  • Resolve merge conflicts

    Hello,

    I’m currently working on a .ufo based project with multiple people and our general idea was to have multiple branches and merge them later.

    Our repository looks like this:
    • master
    • staging
    • dev1
    • dev2
    • …

    The master is supposed to be the "release" branch.
    Staging is where all the margin is supposed to happen and every developer has its own branch to work on the ufo.

    Now im running into the following problem:
    dev1 and dev2 checkout the staging branch to be up to date. Then they work separately in their branches, dev1 draws one letter, dev2 draws another letter.
    They both commit and push and make a merge request.
    I accept the first merge request into the staging branch and everything works fine. The second merge request however produces a merge conflict since there are different keys and strings in the contents.plist file

    Bildschirmfoto 2020-03-26 um 15.04.40.png

    My question is now: what is the best way to solve this merge conflict?
    As of now I manually add the lines from the second merge request into the contents.plist file of the file on the staging branch. It works, but I’d rather not do it every time somebody makes a merge request.

    Add: A possible solution could also be a complete rework of this workflow I described if anybody knows anything better.

    Thanks a lot in advance!



  • I tried to ignore the contents.plist for commits, but that resulted in a lot of RF crashes (in hindsight actually expected behaviour since in future pulls there is just no contents.plist and the UFO’s are corrupted).

    The .glif files however inside the UFO don't produce merge conflicts. So I’m now just resolving merge conflicts by just accepting one version (doesn't matter which one) and then rebuild the contents.plist with your script.

    So, thanks again!



  • @frankrolf said in Resolve merge conflicts:

    Probably it would be a smart approach to make shared files like contents.plist not change. This could be done by assigning a character set from the very beginning (by just giving glyphs an advance width, and thus creating a “full” contents.plist file).

    That was exactly my initial thought for an easy solution. So far it worked quite well, but I wanted to see if there are other solutions since this one seemed not very "professional" to me.
    But I guess if it fits it sits.

    Thank you Frank!



  • Probably it would be a smart approach to make shared files like contents.plist not change. This could be done by assigning a character set from the very beginning (by just giving glyphs an advance width, and thus creating a “full” contents.plist file).
    Another method might be just ignoring the contents.plist file, and re-writing it based on which glyphs came in with the latest commit.
    Coincidentally, I’ve written a script which creates that file based on the contents of the file.ufo/glyphs folder:

    import os
    import plistlib
    import sys
    import xml.etree.ElementTree as ET
    
    
    def write_contents_plist(ufo_path):
        glyph_dir = os.path.join(ufo_path, 'glyphs')
        glif_files = [
            file for file in os.listdir(glyph_dir) if
            os.path.splitext(file)[-1] == '.glif']
    
        d_dict = {}
    
        for glif_file in glif_files:
            glif_path = os.path.join(glyph_dir, glif_file)
            tree = ET.parse(glif_path)
            root = tree.getroot()
            # we need to enter the XML file to find out the
            # glyph name assigned in the UFO
            gname = list(root.findall(".")[0].items())[0][1]
            d_dict[gname] = glif_file
    
        pl_path = os.path.join(ufo_path, 'glyphs', 'contents.plist')
        with open(pl_path, 'wb') as pl_file:
            plistlib.dump(d_dict, pl_file)
    
        print('done')
    
    
    ufo_path = sys.argv[-1]
    if os.path.exists(ufo_path) and os.path.isdir(ufo_path):
        write_contents_plist(ufo_path)
    else:
        print('Please supply a UFO file.')
    


  • Hi Frank,

    thanks for the advice, I’ll look into and try the ufoNormalizer.

    I was hoping to avoid scripting by using a staging branch with a master UFO. but I didn’t know exactly how the contents.plist behaved until now.



  • Hi Daniel,

    The first step toward a clean history is committing normalized UFOs only, see here: https://github.com/unified-font-object/ufoNormalizer

    The UFOnormalizer ensures that files are written in the same way, no matter which tool touches them. It adds time (closing UFOs, normalizing them, committing them, re-opening, etc.) but that’s less time spent than resolving merge conflicts.

    Personally, I have avoided a bunch of conflicts by writing a script which “ingests” changes into a master UFO. That way, there is a clearer history (since only one person is in charge of making commits) and the potential for conflicts is a bit minimized.


Log in to reply