How to back up overwritten files with rsync

Updating a live directory with rsync normally replaces the receiver's previous file as soon as the transfer succeeds. A separate backup directory keeps that displaced copy available while the live destination advances to the new release.

The --backup-dir option stores overwritten files on the receiving side and also catches destination-only files removed by --delete. For a local sync, the receiver is the local machine; for an SSH push, it is the remote host that owns the destination path. Keep the rollback directory outside the live tree so it cannot be copied into or served with the release.

Use a fresh backup directory for every run that needs its own rollback point. Reusing the same directory can replace an earlier backup when the same relative path changes again. A dry run with itemized changes should show the overwrite and every deletion before the live command is allowed to modify the destination.

Steps to back up overwritten files with rsync:

  1. Choose the source, live destination, and receiver-side rollback directory.
    Source: /srv/release/
    Live destination: /srv/www/
    Rollback directory: /srv/rollback/2026-07-11/

    The trailing slash on /srv/release/ copies the directory contents into /srv/www/. Use a unique timestamp or release identifier instead of reusing this sample date.

  2. Create the rollback directory with access limited to the account that runs rsync.
    $ install -d -m 0750 /srv/rollback/2026-07-11

    For an SSH push, create this path on the remote receiving host. An absolute path avoids the destination-relative behavior of a relative --backup-dir value.

  3. Preview the overwrite and deletion.
    $ rsync -ain --delete --backup-dir=/srv/rollback/2026-07-11 /srv/release/ /srv/www/
    *deleting   obsolete.html
    >f.st...... index.html
    >f+++++++++ notes.txt

    --delete moves destination-only files into the rollback directory during the live run. Stop if a *deleting line names a file that should remain in the live tree.

  4. Run the live sync after every previewed change is expected.
    $ rsync -ai --delete --backup-dir=/srv/rollback/2026-07-11 /srv/release/ /srv/www/
    *deleting   obsolete.html
    >f.st...... index.html
    >f+++++++++ notes.txt
  5. Confirm the live destination now contains the source files.
    $ ls -1 /srv/www
    index.html
    notes.txt
  6. List the rollback directory on the receiving side.
    $ ls -1 /srv/rollback/2026-07-11
    index.html
    obsolete.html

    The overwritten index.html and deleted obsolete.html keep their destination-relative names because no backup suffix was set.

  7. Read the overwritten copy from the rollback directory.
    $ cat /srv/rollback/2026-07-11/index.html
    release 1
  8. Check the deleted file's retained content.
    $ cat /srv/rollback/2026-07-11/obsolete.html
    retired page