Skip to content
Git Basics: Compare Arbitrary Files with diff --no-index

Git Basics: Compare Arbitrary Files with diff --no-index

October 27, 2026

Git can compare two filesystem paths even when their contents are not tracked. git diff --no-index is useful for reviewing generated files or exports. Its exit status distinguishes equal content from differences, so a difference should not be treated as a crashed command.

Prepare a scratch directory

Tested on Linux with Git 2.52.0 and GNU Bash 5.2.37. You need the named runtime, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The script creates a second temporary fixture directory and removes only that directory through its exit trap. Run it in a normal Bash terminal, outside any Git hook or Git wrapper. No global Git configuration is changed.

Keep using the same terminal. Stop if setup fails, before saving the source:

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

Run the example

Save this as demonstrate-diff-no-index.sh:

#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
fixture_dir="$(mktemp -d)"
trap 'rm -rf -- "$fixture_dir"' EXIT
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_GLOBAL=/dev/null
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
git init -q -b main "$fixture_dir/repo"
cd -- "$fixture_dir/repo"
git config user.name 'Practice Author'
git config user.email 'practice@example.invalid'
printf 'mode=preview\ncount=2\n' > before.txt
printf 'mode=ready\ncount=2\n' > after.txt
if git diff --no-index --no-color --no-prefix -- before.txt after.txt > change.patch; then
  exit 1
else
  status=$?
  test "$status" -eq 1
fi
printf 'Difference status: %s\n' "$status"
cat change.patch
cp before.txt identical.txt
git diff --no-index --quiet -- before.txt identical.txt
printf 'Identical content status: %s\n' "$?"
test "$(cat before.txt)" = "$(cat identical.txt)"

Run it:

bash demonstrate-diff-no-index.sh

Observed output:

Difference status: 1
diff --git before.txt after.txt
index 866b7b7..3cdd24e 100644
--- before.txt
+++ after.txt
@@ -1,2 +1,2 @@
-mode=preview
+mode=ready
 count=2
Identical content status: 0

Read the result

--no-index selects a path-to-path comparison and implies exit-code behavior: zero for equality and one for differences. The script captures the differing patch, checks status one explicitly, and then compares an identical copy. --no-color keeps terminal escape sequences out of the saved patch; --no-prefix simplifies the displayed path names.

Apply it carefully

A status greater than one indicates a problem rather than an ordinary difference. Preserve that distinction in CI instead of using a blanket || true. This example compares text files, but binary files and directories have different output shapes. The index header identifies content, and its abbreviations are not a replacement for storing the full inputs. Review a generated patch before applying it elsewhere; this tutorial only compares and never applies changes.

The official reference describes the API and its options. The checks above cover the specific fixture, not every possible input or environment.

Clean up

Remove the source and then the empty practice directory:

rm -- demonstrate-diff-no-index.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

If the directory is not empty, inspect the remaining files rather than deleting unknown contents.

Acknowledgements

This post was created with assistance from AI.

Last updated on