Alex Riesen <raa.lkml@xxxxxxxxx> writes: > This patch leaves the base name in the resulting intermediate tree, to > propagate the conflict from intermediate merges up to the top-level merge. > --- I've eyeballed not your patch but the entire merge-recursive again, to make sure that the codepath you are touching is the only one that can potentially leave higher stages in the index for intermediate merge. Anything that calls update_file() for intermediate merge ends up doing add_cacheinfo() hence drops higher stages for that path, and it seems that the function you are changing, conflict_rename_rename, is the only one that leaves unmerged entries in the tree, so I think thi is good. The assertion you added to git_write_tree() is good way to catch if the above assumption was wrong and we missed other codepaths. > The result seem to be at least predictable. Still, doesn't it mean > that once a rename/rename conflict is in it has to be resolved > manually forever? That's certainly better than segfaulting, and in my opinion, it is much better than silently giving a wrong merge result assuming one conflict resolution. We've been resolving other cases that we should not usually resolve for intermediate merges, leaning on the safer side. For example, look at what delete/modify does for an intermediate merge. It leaves the modified contents in the index. The reason an intermediate merge conflicts is because the two branches resolved the same (not necessarily "exactly the same") merges differently earlier. That means the two people who made those ancestor merges could not agree on something. Because they could not agree on, you end up being responsible for reconciling their differences in opinion. I do not think it is a bad thing -- in fact, I even think it is a good thing. Forks do not have to converge and you have an opportunity to decide which side you are on for yourself. An illustration. Suppose there is a project that has incorrect documentation, and Alice and Bob worked on it separately. Alice finds the documentation's language horrible and makes typofixes, while in Bob's opinion its contents, even if its language were to be improved, keeping the incorrect documentation spreads misinformation and it is worthless. Bob deletes the incorrect documentation and keeps working on other things. .------------A1--A2------------A / modify doc \ / take "modify" / X and later improve / / \ ---o---------------B1---B2------------B delete doc take "delete" In short, Alice modified and Bob deleted, and reached point A1 and B1, respectively. Now Alice pulls from Bob, hand-resolves the delete/modify and improves the contents to make it not just language clean (which she did in the previous steps leading to A1) but technically accurate. She now is at point A2, but haven't pushed her changes out yet. She continues to work and reaches A In the meantime Bob is making further changes to the parts of the system the documentation used to describe. Bob commits his changes, pulls from Alice's last published one A1, and gets delete/modify conflict in the doc, and he takes the deletion and merge result is B2. He continues to work and reaches B. Later Charlie clones from Bob's B, and tries to merge from Alice's A. There are two merge bases (A1 and B1), so an attempt to merge the merge bases is made by recursive. This gives delete/modify conflict. We leave the modified contents in this intermediate "virtual ancestor" tree, but the end result is that Charlie has a chance to resolve this delete/modify conflict Alice and Bob could not agree on for himself. If Charlie thinks the same way as Alice and it is a good idea to keep the documentation up to date, he might do something like Alice did at A2. If on the other hand Charlie agrees with Bob at B2, he might take delete. I think leaving that decision up to Charlie is not necessarily a bad thing. - 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