Conflict-marker searches cannot establish that a Git merge is resolved. A user may remove every marker from a working file while its index still contains separate merge stages. Conversely, a source file may legitimately contain marker-like text. Query the index directly when a local preflight step needs to detect unresolved entries.

Prerequisites and safe fixture

Use Git and Bash on Linux. This example was executed with Git 2.43.0 and Bash 5.2.21. Run it from a writable scratch directory. It creates a unique child repository and removes only that generated directory on exit. It makes no commits, changes no account identity and contacts no remote. The caller should not supply inherited Git environment overrides when running this self-contained demonstration.

The setup writes three tiny blobs and inserts stages 1, 2 and 3 for report.txt using Git's index plumbing. This creates a genuine unmerged index without needing branch history. The preflight itself uses git ls-files --unmerged -z. NUL-terminated output remains in a temporary file rather than being stored in a shell variable. Only whether the successful listing is empty matters.

Complete example

Save as conflict.sh.

#!/usr/bin/env bash
set -euo pipefail
scratch=$(mktemp -d "$PWD/git-index-demo.XXXXXX")
trap 'rm -rf -- "$scratch"' EXIT
cd "$scratch"
git init -q
base=$(printf 'base\n' | git hash-object -w --stdin)
ours=$(printf 'ours\n' | git hash-object -w --stdin)
theirs=$(printf 'theirs\n' | git hash-object -w --stdin)
# Create a genuine unmerged index without commits, identities or branches.
printf '100644 %s 1\treport.txt\n100644 %s 2\treport.txt\n100644 %s 3\treport.txt\n' \
    "$base" "$ours" "$theirs" | git update-index --index-info
index_ready() {
    git ls-files --unmerged -z > unmerged.bin || return 2
    if [[ -s unmerged.bin ]]; then return 1; fi
    return 0
}
status=0
index_ready || status=$?
[[ "$status" == 1 ]]
printf 'before=blocked\n'
# Editing the working file alone does not resolve the index.
printf 'resolved\n' > report.txt
status=0
index_ready || status=$?
[[ "$status" == 1 ]]
git add -- report.txt
index_ready
printf 'after=ready\n'
# A Git failure must remain distinct from an empty successful listing.
status=0
GIT_DIR=./missing-repository index_ready 2>/dev/null || status=$?
[[ "$status" == 2 ]]
printf 'git-error=2\n'

Run and expected output

bash conflict.sh
before=blocked
after=ready
git-error=2

Interpret the three states

The helper returns zero for a successfully queried index with no unmerged entries, one when unmerged entries exist, and two when Git cannot perform the query. Its explicit error branch matters because an empty output file caused by a failed command must not become permission to proceed. The script deliberately points GIT_DIR at a missing directory to verify that failure remains state two.

The first query blocks. Writing resolved text to the working file still blocks because the index has not changed. After git add -- report.txt, the staged resolution replaces the unmerged stages, and the helper reports ready. The demonstration checks this transition rather than inferring readiness from the disappearance of marker text.

Edge cases and troubleshooting

An empty unmerged listing does not certify that the resolution is correct, that tests pass, or that the working tree is clean. It establishes only that no unmerged index entries were returned. Keep those questions as separate checks. For a real conflict, inspect the file and choose the correct content before staging it; do not run git add merely to silence a gate.

The NUL form avoids treating unusual filename characters as record separators, although this fixture uses an ordinary filename and does not exercise every filename case. If the helper returns two, inspect the unsuppressed Git error in your integration and verify repository selection and permissions. Suppression of stderr appears only in the deliberate missing-repository test. This example tests the actual Git index state; it does not create a real branch merge or validate a particular conflict resolution.

Primary references

Continue with Git tutorials.