diff shows exactly what changed between two files; patch applies such a description to a target. The pair is older than every modern editor's git integration — and still the cleanest vocabulary for "here are my changes" in plain text.

Reading a diff #

Compare two files, unified format
$ diff -u config.old config.new
--- config.old
+++ config.new
@@ -12,4 +12,4 @@
-timeout 30
+timeout 60

The unified format (almost always what you want) shows three lines of context around each change: - lines were removed, + lines added, @@ marks the position. Skim any pull request and you are reading exactly this.

For directories, one flag compares whole trees:

Compare two directories recursively
$ diff -ru old-release/ new-release/ > release.patch

Useful flags #

FlagEffect
-uUnified format, the readable default
-rRecurse into directories
-qReport only which files differ
-wIgnore whitespace changes
-ySide-by-side columns

-q is the fast audit — which files differ at all — before digging into any single pair.

Applying changes #

patch reads a diff and applies it elsewhere, which is how fixes travelled by email for decades and still do in some projects:

Apply a patch, dry-run first
$ patch --dry-run -p1 < fix.patch
$ patch -p1 < fix.patch

The -p1 strips one leading path component — the convention when patches were made from inside a source tree. --dry-run previews without writing; it is the look-before-you-delete habit, translated.

Compare whole directories with find feeding the candidates, and inspect single files with stat, file, and which. More in the terminal notes series.