The answer by Jones Agyemang is probably sufficient for most use cases and was a great starting point for my solution. For scripting in Git Bent, the git wrapper library I made, I needed something a bit more robust. I'm posting the prototype I've written which is not yet totally script-friendly
Notes
- The linked answer checks for <<<<<<< HEADwhich doesn't work for merge conflicts from usinggit stash applywhich has<<<<<<< Updated Upstream
- My solution confirms the presence of =======&>>>>>>>
- The linked answer is surely more performant, as it doesn't have to do as much
- My solution does NOT provide line numbers
Print files with merge conflicts
You need the str_split_line function from below.
# Root git directory
dir="$(git rev-parse --show-toplevel)"
# Put the grep output into an array (see below)
str_split_line "$(grep -r "^<<<<<<< " "${dir})" files
bn="$(basename "${dir}")"
for i in "${files[@]}"; do 
    # Remove the matched string, so we're left with the file name  
    file="$(sed -e "s/:<<<<<<< .*//" <<< "${i}")"
    # Remove the path, keep the project dir's name  
    fileShort="${file#"${dir}"}"
    fileShort="${bn}${fileShort}"
    # Confirm merge divider & closer are present
    c1=$(grep -c "^=======" "${file}")
    c2=$(grep -c "^>>>>>>> " "${file}")
    if [[ c1 -gt 0 && c2 -gt 0 ]]; then
        echo "${fileShort} has a merge conflict"
    fi
done
Output
projectdir/file-name
projectdir/subdir/file-name
Split strings by line function
You can just copy the block of code if you don't want this as a separate function
function str_split_line(){
# for IFS, see https://stackoverflow.com/questions/16831429/when-setting-ifs-to-split-on-newlines-why-is-it-necessary-to-include-a-backspac
IFS="
"
    declare -n lines=$2
    while read line; do
        lines+=("${line}")
    done <<< "${1}"
}