Search code examples
gitgit-merge-conflict

How does git figure out unmerged paths in conflicts?


How does git get the list of unmerged paths?

My understanding of git is that when merging it incorporates changes into a file and then adds it to index. If a merge conflict occurs, a file is not added to the index and is left in the working tree with conflict markers. If I run git status it shows me unmerged paths for the conflicted files.

How does git get the list of these files? If I run git add for a conflicted file with markers still in place, it will not be shown as conflicted anymore, so perhaps markers are not identifiers?


Solution

  • If merge conflict occurs a file is not added in index and left in working tree with conflict markers.

    It is in the index: see git ls-files:

    For an unmerged path, instead of recording a single mode/SHA-1 pair, the index records up to three such pairs; one from tree O in stage 1, A in stage 2, and B in stage 3.

    git read-tree details the 2 way merge:

    Each "index" entry has two bits worth of "stage" state.
    stage 0 is the normal one, and is the only one you’d see in any kind of normal use.

    However, when you do git read-tree with three trees, the "stage" starts out at 1.

    This means that you can do

    git read-tree -m <tree1> <tree2> <tree3>
    

    and you will end up with an index with all of the <tree1> entries in "stage1", all of the <tree2> entries in "stage2" and all of the <tree3> entries in "stage3".
    When performing a merge of another branch into the current branch, we use the common ancestor tree as <tree1>, the current branch head as <tree2>, and the other branch head as <tree3>.

    See also "How do I force git to think a file is unmerged?".