Hi Elijah, Elijah Newren wrote: > # B D > # o---o > # / \ / \ > # A o X ? F > # \ / \ / > # o---o > # C E > In other words, there > > Let's start with a simple though very contrived case that will > illustrate issues later, namely a repository with exactly one file > named 'file', with the following contents at different points in > history: > > Commit A: file has contents 'A\n' > Commit B: file has contents 'B\n' > Commit C: file has contents 'C\n' > Commit D: file has contents 'D\n' > Commit E: file has the following 5 lines in it: > <<<<<<< Temporary merge branch 1 > C > ======= > B > >>>>>>> Temporary merge branch 2 > > Now, if we try to merge D & E, clearly there should be a conflict. > But git merges cleanly, giving file the contents 'D\n'. Funny. A different problem is that with a less unusual history (i.e. no conflict hunks committed) with "[merge] conflictstyle=diff3", if there are conflicts in an early stage of recursive merge, we get nested conflict hunks, leaving rerere and humans confused. I have wondered: why doesn't merge-recursive implicitly use the union merge driver for its in-core merge of ancestors? The resulting diff3-style conflict hunks from the final 3-way merge would be more readable, but now you've provided an answer: coincidences of matching content like you describe would become more likely. [...] > It's wrong, but the only way to fix it is to somehow have an entry in > the virtual ancestor tree where the conflict region(s) of file are > guaranteed to not match the corresponding content locations of file > for either D or E. (Perhaps by adding random content on the line > after the ='s?) Random content does not provides a guarantee. Maybe merge_recursive()/merge_trees() could steal a flag bit from struct object for "conflicted"? No, that would give only one bit for the entire tree, and we need one bit per path. How about using index entries for this? >From the signature of git_merge_trees(1, ...) it is not obvious to me where it reports conflicts. From the start to write_tree_from_memory() I would guess it does not at all. [...] > Possibility 1: Virtual ancestor somehow contains both 'a' and 'a/file' > (currently impossible in git, since this virtual ancestor is written > as a tree [...] > The only way out of this that I see (and I'm hoping I'm just missing > something), is a modification of possibility 1: make the virtual > ancestor contain both 'a' and 'a/file' Hmm, D/F is a little harder than the content conflict case, I guess. ;-) But I think in general, the thing to do is to keep something other than a tree. Thanks for the food for thought. Jonathan -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html