Search code examples
gitgit-submodules

How to identify merge conflicts in submodule references before doing a merge?


I am trying to build a script to handle merge conflicts automatically under certain conditions. I find it challenging to identify merge conflicts in submodule references without doing a merge.

I mean, I would like to find a simple way to identify merge conflicts in submodule references between two branches before doing the merge (even if it is not committed).

When I say submodule references, I don't mean conflicts within the submodule. Rather what I mean can be explained in an example that if the submodule in branch A (in my parent repository) is pointing to reference X and the same submodule in branch B (in my parent repository) is pointing to reference Y. This will cause a conflict if the submodule reference was updated in both branches and it looks like this in SourceTree:

Example of submodule reference conflicts and no conflicts

As you can see, one submodule reference PNG_ND_Drivers does not have a conflict, and the other one EmbeddedSW_UnitTests, does have a conflict. The changes appear to be of the same nature. There is no way to identify from the changes in the files that there is a conflict. So how can I identify it before doing a merge?

Note: I can do a merge with the --no-commit flag and then review the status of the files using git status --short and find under

Unmerged paths:
            both modified: EmbeddedSW-UnitTests

whereas the other submodule appears under:

Changes not staged for commit:
            modified: PNG_ND_Drivers (new commits)

So I could identify the conflict this way. But I would need to do the merge and then abort and discard it. It seems too cumbersome, so I wanted to ask if someone knows of a way to do it more efficiently.


Solution

  • Although @Lucas Oshiro did provide a general methodology for finding conflicts in submodules, I prefer to use a more simpler approach with git merge-tree --write-tree that does not require mentioning any submodule name and requires fewer commands:

    # Define the branches
    origin_branch="$(git rev-parse --abbrev-ref HEAD)"
    destination_branch="origin/main"
        
    # Perform the merge-tree command and capture the output
    merge_output=$(git merge-tree --write-tree --name-only $origin_branch $destination_branch)
        
    # Extract submodule names with conflicts from the merge output using grep and store in an array
    mapfile -t conflicted_submodules < <(echo "$merge_output" | grep -E '^CONFLICT.*submodule' | awk '{print $NF}')
        
    # Display the list of submodule conflicts
    echo "Conflicts found in the following submodules:"
    printf '%s\n' "${conflicted_submodules[@]}"