Yaroslav Halchenko wrote [abbreviated]: > CONFLICT (file/directory): There is a directory with name frontiers/code in todonotloose. Adding frontiers/code as frontiers/code~HEAD > % git ls-files -u > 160000 a2b5787 2 frontiers/code > % git diff-tree todonotloose > a00c497 > :040000 040000 40427e3 c7ba910 M poster-hbm2011_neurodebian > % git diff-tree todonotloose^ HEAD > :100644 100644 378e137 c39ced7 M .gitmodules > :000000 040000 0000000 141dbc1 A challenge-execpapers > :040000 040000 401fd66 ee190f0 M frontiers > :040000 040000 26c884a ad3e829 M sty Here is what happens. In the heart of merge_trees: /* * If there are D/F conflicts, and the paths currently exist * in the working copy as a file, remove them to make room * for the corresponding directory. Such paths will later be * processed in process_df_entry() at the end. * * If the corresponding directory ends up being removed by the * merge, then the file will be reinstated at that time; * otherwise, if the file is not supposed to be removed by the * merge, the contents of the file will be placed in another * unique filename. */ make_room_for_directories_of_df_conflicts(o, entries); In this case I suppose it is rather a directory/submodule conflict; in any case, there are no regular files involved, so this logic does not kick in and the directory is left alone. Next comes rename handling, which is irrelevant for our purposes. Next comes the per entry merge. /* * Per entry merge. D/F conflicts are deferred so files * contained in such a directory can be resolved first. */ for (i = 0; i < entries->nr; i++) { const char *path = entries->items[i].string; struct stage_data *e = entries->items[i].util; if (!e->processed && !process_entry(o, path, e)) clean = 0; } This is case B: "added in one" (like all directories, the frontiers/code directory does not have an index entry, while the submodule does have one). Since that path is in the current directory set, it is deferred for later processing. Next comes the per entry merge for D/F conflicts (process_df_entry in merge-recursive.c). This is the case "directory -> (directory, file)". Unfortunately the check that the old and new directories match is not implemented. Even worse, git checks for a directory (which was not moved out of the way before) and does not realize that a submodule might be another reason for a directory in the worktree. In any event, we get a spurious conflict. Thanks, that was interesting (no patch yet, alas). -- 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