NS-084
documentedchange-invisible-to-the-comparison
A file that changed without changing size or timestamp is never transferred
- reads as
- `rsync -a src/ dst/` exits zero, and dst/app.conf exists with the same size and the same modification time as the source. Conclusion drawn: the destination is a copy of the source.
- actually
- rsync(1): rsync finds files that need to be transferred using a 'quick check' algorithm (by default) that looks for files that have changed in size or in last-modified time. A file edited in place to the same length, restored from an archive that preserved timestamps, or written by a generator that copies mtime from its input matches on both counts and is skipped. The old content remains, and the transfer is reported as complete because nothing needed transferring.
- blind because
- The two numbers the tool decides on are the two numbers used to verify it. Size and mtime agree, which is a true statement about the metadata and a false one about the contents.
- the check
- Compare contents rather than metadata: `rsync -ain --checksum src/ dst/` lists exactly what a content comparison would move. Observed on rsync 3.2.7 with src/app.conf holding VERSION=2 and dst/app.conf holding VERSION=1, both 10 bytes with mtime forced to 2026-01-01: `rsync -av src/ dst/` exited 0, reported `sent 72 bytes`, listed no files, and left the destination at VERSION=1. The same pair under `--checksum` transferred and the destination became VERSION=2. `cp -u` copied nothing for the same reason.
- cost of missing
- A deploy or backup succeeds and changes nothing, and repeating it reproduces the same success, so the obvious response to the symptom confirms the wrong hypothesis.
- mitigation
- Use `--checksum` for any sync where the content is authoritative and the timestamps are not, accepting the read cost; or ensure the writer touches mtime whenever it rewrites.
- generalises to
- Every change detector keyed on a proxy for content: mtime-based build systems, ETags derived from metadata, cache keys built from a version string that was not bumped.
- source
- man7.org