On Tue, Jan 23, 2018 at 7:08 AM, Josh Bleecher Snyder <josharian@xxxxxxxxx> wrote: > Looking over your list above, at a minimum, libgit2 might not have a > particularly good way to represent submodule/file or > submodule/directory conflicts, because is-a-submodule is defined > external to a git_index_entry. libgit2 should detect submodule/file and submodule/directory conflicts. While, yes, some metadata about the submodule is located outside the index, you can look at the mode to determine that this _is_ a submodule. You should be able to reliably detect submodule/file conflicts because one will be a regular or executable file (mode 0100644 or 0100755), while the other entry at the same path will be a gitlink (mode 0160000). Similarly, submodule/directory conflict detection works just like regular file/directory conflict detection. If some path `foo` is a submodule (or a regular file) then some path `foo/bar` existing in the other side of the merge causes a conflict. > Cataloging or special-casing all possible conflict types does seem > unwise because of the sheer number of kinds of conflicts. > > But the alternative appears to be punting entirely, as libgit2 does, > and merely providing something akin to three index entries. Indeed, when I added merge to libgit2, we put the higher-level conflict analysis into application code because there was not much interest in it at the time. I've been meaning to add this to `git_status` in libgit2, but it's not been a high priority. > This which > leaves it unclear what exactly the conflict was, at which point any > user (read: porcelain developer) will end up having to recreate some > merge logic to figure out what went wrong. And if merge-tree starts > doing rename detection, the user might then have to emulate that as > well. That's not a good idea. Trying to figure out what merge did would be painful at best, and likely impossible, since a rename conflict is recorded in the main index without any way to piece it together. eg: 100644 deadbeefdeadbeefdeadbeefdeadbeefdeadbeef 1 bar.c 100644 cafec4fecafec4fecafec4fecafec4fecafec4fe 2 bar.c 100644 c4cc188a892898e13927dc4a02e7f68814b874b2 1 foo.c 100644 71f5af150b25e3aaaad2d67ff46759311401036f 2 foo.c 100644 351cfbdd55d656edd2c5c995aae3caafb9ec11fa 3 rename1.c 100644 e407c7d138fb457674c3b114fcf47748169ab0c5 3 rename2.c This is the main index that results when bar.c has a rename/edit conflict, and foo.c also has a rename/edit conflict. One was renamed to rename1.c and the other to rename2.c. Trying to determine which is which _after the fact_ would be regrettable. Especially since rename detection is not static - you would need to know the thresholds that were configured at the time merge was performed and try to replay the rename detection with that. libgit2 records a `NAME` section in the index that pairs the rename detection decisions that it performed so that you can analyze them and display them after the fact. -ed