Everything you need to know about Rsync

Abstract generated cover for Everything you need to know about Rsync.

I use `rsync` any time I need to move a pile of files between machines and I want it to be fast, repeatable, and safe. It is one of those tools that feels boring until you try to replace it with “just scp”, re-uploading whole folders over and over, and wondering which copy is the real one.

What rsync is (in plain terms)

`rsync` is a file synchronization tool. It compares a source and a destination, figures out what changed, and then transfers only what it needs to transfer. Most of the time you use it to:

  • push a local folder to a server
  • pull a server folder down to your machine
  • keep two directories in sync
  • do backups without rewriting everything each run It works locally too, but the real magic is pairing it with SSH.

The mental model: copy, but smarter

A decent way to think about rsync is:

“It’s copy with a brain. It looks first, then moves only the difference.” On the first run, it will copy everything. On the second run, it will mostly do nothing — because it can see the destination is already up to date. That makes rsync perfect for:

  • iterating on a project deployed to a server
  • incremental backups
  • syncing photo libraries or media folders
  • migrating a directory structure without losing timestamps/permissions

How it works (the parts you actually need to know)

There are three ideas that matter in practice:

1) It does a file list + comparison step first

Rsync scans the source, scans the destination, and decides what needs to happen. That means it is usually safe to run multiple times. It is designed for “run it again” workflows.

2) It can preserve metadata

With the right flags, rsync keeps:

  • timestamps
  • permissions
  • symbolic links
  • directory structure That is a big deal for code deployments and backups.

3) It can transfer only the changed parts of a file

For large files, rsync can use a “delta” algorithm: instead of sending the whole file, it can send just the changed blocks. This is not always a huge win (and sometimes compression is enough), but when it matters, it really matters.

The one option I use constantly: `-a`

`-a` means “archive mode”. It’s basically the “do the right thing” preset:

  • recursive copy
  • preserve timestamps
  • preserve permissions (as possible)
  • preserve symlinks So most real rsync commands start with:
rsync -a ...

The other option that makes rsync pleasant: `-v` (and sometimes `--progress`)

  • `-v`: verbose output (show what it’s doing)
  • `--progress`: show per-file progress (useful for big transfers) Example:
rsync -av --progress source/ destination/

The most important thing to get right: trailing slashes

This is where people get burned.

If the source has a trailing slash

rsync -av my-folder/ user@server:/var/www/my-folder/

This means: “sync the contents of `my-folder` into the destination folder.”

If the source does NOT have a trailing slash

rsync -av my-folder user@server:/var/www/

This means: “copy the folder `my-folder` itself into `/var/www/`.” Rsync is precise. It will do exactly what you told it to do. When in doubt, use `--dry-run` first.

Don’t guess: use `--dry-run`

`--dry-run` shows what would happen without actually copying anything.

rsync -av --dry-run my-folder/ user@server:/var/www/my-folder/

If you are about to delete or overwrite important files, `--dry-run` is the difference between confidence and regret.

Connecting a Mac to an Ubuntu server (SSH + rsync)

Most of the time, you run rsync “over SSH” like this:

rsync -av -e "ssh" local-folder/ user@your-server:/path/on/server/

But before rsync, make sure the SSH part is clean.

Step 1: verify you can SSH in

From your Mac:

ssh user@your-server

If that works, rsync will work too.

Step 2: (recommended) use SSH keys

On your Mac:

ssh-keygen -t ed25519 -C "mac-to-ubuntu"

Copy your public key to the server:

ssh-copy-id user@your-server

If `ssh-copy-id` isn’t available on your Mac, you can do it manually:

cat ~/.ssh/id_ed25519.pub | ssh user@your-server 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'

Now you should be able to:

ssh user@your-server

without typing a password every time.

Example 1: deploy a local folder to Ubuntu

Say you have a local project folder: ```plain text ~/Projects/my-site/

And you want it on the server:
```plain text
/var/www/my-site/

Run:

rsync -av --delete -e "ssh" ~/Projects/my-site/ user@your-server:/var/www/my-site/

What the key pieces mean:

  • `--delete`: remove files on the destination that no longer exist in the source (keeps it truly in sync)
  • `-e "ssh"`: use SSH as the transport Be careful with `--delete`. It is correct for deployments, but you should dry-run the first time:
rsync -av --dry-run --delete -e "ssh" ~/Projects/my-site/ user@your-server:/var/www/my-site/

Example 2: pull server logs down to your Mac

Pulling data down is the same idea, reversed:

rsync -av -e "ssh" user@your-server:/var/log/nginx/ ~/Downloads/nginx-logs/

Example 3: sync over a custom SSH port

If your server SSH runs on a non-standard port (say 2222):

rsync -av -e "ssh -p 2222" local-folder/ user@your-server:/path/on/server/

Example 4: exclude junk files

Excluding things is part of the workflow.

rsync -av --delete \
    --exclude ".DS_Store" \
    --exclude "node_modules/" \
    --exclude ".venv/" \
    -e "ssh" \
    ./ user@your-server:/var/www/my-site/

Example 5: backup your home folder (without doing something reckless)

This is a reasonable pattern for backups to a server directory:

rsync -av --progress \
    --exclude "Downloads/" \
    --exclude ".Trash/" \
    -e "ssh" \
    ~/ user@your-server:/backups/macbook-home/

If you want a “mirror” backup, you might add `--delete`, but only if you actually want deletions reflected in the backup.

Common mistakes (and how to not make them)

Mistake 1: using rsync without `-a`

If you don’t preserve timestamps/structure, you can end up with weird “everything changed” behavior on the next run. Start with `-a`.

Mistake 2: forgetting the trailing slash

It changes the meaning of the command. If your destination ends up with `my-folder/my-folder/`, this is usually why.

Mistake 3: using `--delete` without a dry run

If the path is wrong, you can delete the wrong destination content. Use:

rsync -av --dry-run --delete ...

Mistake 4: not quoting the SSH command

If you add SSH flags, quote it:

rsync -av -e "ssh -p 2222" ...

A practical “starter command”

If you want a baseline command for syncing a local folder to an Ubuntu server:

rsync -av --progress --dry-run --delete -e "ssh" ./ user@your-server:/path/on/server/

Remove `--dry-run` once it prints exactly what you expect.

Key takeaways

  • Rsync is about repeatable sync, not one-off copying.
  • `-a` is the default mode you want.
  • Trailing slashes matter.
  • `--dry-run` is your safety net.
  • Over SSH, rsync is one of the cleanest “Mac to Ubuntu server” file transfer workflows.

← Back to Blog Index