Which workflow can lead to "added by them" conflict in Git?

Viewed 178

I am doing a non-trivial merge and I see "added by them" conflict for a file which was missing on 'ours' branch. Usually Git merges added files with ease but looks like this was some strange history which resulted in "added by them" conflict.

Can you Git experts explain this somehow?

1 Answers

We're given a few things: we know that a merge (at least in Git) is by definition the result of three inputs:

  • merge base commit;
  • ours or HEAD or "local" commit;
  • and theirs or "remote" or "other" commit;

An added file means "some file was not present in the merge base". If we added the file (in the ours/HEAD/local commit), it's new in our commit. If they added the file, it's new in their commit. If both added the file, that's a conflict. But here, you see only one side as having added the file. That's normally not a conflict at all: as you say, Git just decides they added a new file, so the new merge commit should have their added file.

What we really need here—but don't have—is the output from Git at the time you ran git merge. (If you do have it, e.g., in scrollback in some window, scroll back and get it.) What I have observed here is post-merge-conflict confusion by Git, in terms of the traces left in Git's index, after a rename.

When there is a rename, especially one that takes place only on one "side" of the merge, or takes place but differently on both sides, Git has a problem. If the file named f-base became f-ours in our commit and f-theirs in their commit, for instance, which name should Git use?

The traces Git leaves in the index for this particular case are (at least sometimes, in my observations):

  • There is a file named f-base in slot 1, but nothing in slots 2 and 3 for the name f-base.
  • There is a file named f-ours in slot 2, but nothing in slots 1 and 3 for the name f-ours.
  • There is a file named f-theirs in slot 3, but nothing in slots 1 and 2 for the name f-theirs.

While git merge correctly prints this as a rename/rename conflict during the merge, git status later diagnoses this as added by us: f-ours and added by them: f-theirs. There's no serious conflict with f-base (it's "deleted by both" so it should just be deleted from the working tree too) but the correct final name is not obvious. The working tree gets one of the two names and git status complains about the other one.

The index needs to record some sort of linkage from the old to new names here, and git status needs to recover it. But this case is rare enough that I haven't seen it often enough to even have written up a reproducer, much less see whether it still occurs today and whether the new merge-ort algorithm handles this better.

Related