Minimize Merge Diff

Issue #1902 resolved
Jacob Mather created an issue

When a conflict is detected while uploading a changed file, the diff presented is a directory comparison even when only a single file is in conflict, which leads to having to scroll down a long way to find the file you’re trying to diff.

Comments (5)

  1. Scott Wells repo owner

    Jacob, what kind of file is it? If it has a companion meta.xml file, e.g., an Apex class/trigger, Visualforce page/component, static resource, etc., then it's because two files were retrieved and not just the single conflicting file. IC2 does try to minimize the diff, both drilling down to the lowest parent directory that's shared by all diffed files or, if there's exactly one file, it switches to a file diff for just that file.

    It's arguable that perhaps it shouldn't include the meta.xml file, but it's always possible that the conflict exists because metadata was changed on the server, e.g., the API version number for an Apex class, rather than the class source itself.

    If you're finding this to be happening for metadata types that don't have supporting meta.xml files, please let me know and I'd like to see a debug log. IC2 generally says why it chooses to diff at a specific level once you crank up debug logging.

  2. Jacob Mather reporter

    This specific one was an apex class.

    So, for example, we have 318 apex classes.

    If I edit a file and upload it, and it detects a conflict, and i hit the ‘merge’ button (sorry, generalizing, since i’m going off of memory here), then i get a directory view diff w/ the entire contents of the “classes” directory on the right, and the left i’m stuck looking for the single entry (though it now occurs to me that filtering by name on the left column might help?).

    This also happens if I right click on a single file and hit “retrieve metadata”.

    I think if this is just due to a limitation of how IntelliJ handles some of the actions, then perhaps what needs to be done is a change like:

    Supposition of current system:

    1. Define set to download for update
    2. Download payload
    3. Unzip payload to tmp location
    4. trigger merge diff between tmp location and target directory path

    Tweak for revised behavior:

    1. same
    2. same
    3. same
    4. use set defined in 1 to cherry pick a separate copy of the change set from the current working copy files

      1. so now you have like, /tmp/downloaded-updates and /tmp/original-copy
      2. you don’t want to use the downloaded payload as the basis as it would miss
    5. set up watchers for the files in /tmp/original-copy (including paths present in downloaded-updates but not original-copy) to replicate changes to the actual working copy files.

    6. trigger original step 4 but target from=downloaded-updates and to=original-copy

    I dunno. Seems kinda a pain. It’s obnoxious enough to me that if you gave me code and direction of where to start I’d happily figure it out eventually… 😃 But I dunno how you are on src availability and such.

  3. Scott Wells repo owner

    Hi, Jacob. Yes, what you described matches my description as well. Basically IC2 sees that an Apex class scheduled for deployment may have a conflict with the server version. It informs the user, and the user chooses to compare/merge the local and server versions. Two files get retrieved, MyClass.cls and MyClass.cls-meta.xml. The former is of course the class definition, and the latter is the metadata for that class. Either one of those files could be the reason for the perceived conflict. For example, if another user changed the class' API version but not the class body itself, and you changed the class body, that's a conflict that cannot be resolved using just MyClass.cls.

    When IC2 looks at what was retrieved and sees more than one file, it tries to find the closest common root directory for all retrieved files as the basis for the comparison. In this example, that would be the parent classes directory, hence why it's showing the retrieved class/metadata files on the left and all contents of the project's classes directory on the right. That way you can reconcile both aspects of the potentially conflicting metadata.

    If instead a potential conflict had been found in a metadata object that exists in exactly one file, e.g., Account.object, a file diff would be used instead of a directory diff.

    The only way I've determined to address this would be to perform a first-pass analysis on the retrieved files and their local counterparts and remove those that are identical from consideration when setting up the diff. So if the MyClass.cls files were different but the MyClass.cls-meta.xml files were the same, the former would be diffed directly. The big wrench in the gears with this approach is that there can be minor changes in the retrieved metadata files, e.g., line endings, minor whitespace changes, etc., that lead to false conclusions.

    One thing you can do that helps significantly is toggle the Show New Files on Right Side off during these diffs:

    Issue_1902_Diff.png

    That will show you exactly what was retrieved against the local counterparts. Of course, you'd only want to do that when you know that you're comparing exactly a server copy to a local copy. Otherwise you do want to show orphans as they represent a significant aspect of the server/local state difference.

    And yet another option--the one I use--is to configure the IDE for an external diff tool like Beyond Compare (or Araxis Merge, etc.) that does a much better job of letting you sort through diffs at both the directory and file levels.

    Hope that helps!

  4. Scott Wells repo owner

    Issue tracker grooming. If this is still an issue, please feel free to reopen, ideally with a concrete reproduction scenario.

  5. Log in to comment