rsync --delete: Mirroring and Its Dangers in CI
rsync --delete deletes files on the destination that are not present in the source, making the two sides match exactly.
Mirroring a deploy with --delete keeps the server clean of stale assets, but a wrong source path can wipe a directory. Test with --dry-run first.
What it does
--delete removes files in the destination that have no counterpart in the source, so the destination becomes an exact mirror. This is how you avoid orphaned old bundles piling up on a web server. It is also the flag most likely to cause data loss in CI if the source path is wrong.
Common usage
# Mirror dist/ to the server, removing stale files
rsync -av --delete dist/ user@host:/var/www/app/
# Preview deletions before committing
rsync -avn --delete dist/ user@host:/var/www/app/Delete variants
| Flag | What it does |
|---|---|
| --delete | Delete extraneous files from the destination |
| --delete-after | Delete after the transfer (safer if it aborts) |
| --delete-excluded | Also delete files the filters exclude |
| --delete-delay | Find deletions during transfer, remove at the end |
| --max-delete=N | Abort if more than N files would be deleted |
In CI
Always pair --delete with --max-delete=N in automation. If a build step fails and produces an empty dist/, a bare rsync --delete will happily delete the entire live site. With --max-delete=100 the run aborts with "rsync error: the --max-delete limit stopped deletions" before damage is done.
Common errors in CI
The classic mistake: "rsync -av --delete dist user@host:/var/www/" (no trailing slash on dist) copies dist INTO /var/www and deletes the rest of /var/www. Use a trailing slash on the source (dist/) so the contents, not the directory, are mirrored. See the trailing-slash page.