# Migrating Existing Data

`swarmfile-migrate` is a standalone CLI for bulk-importing data you already have into a Swarmfile project - a NAS share, a flat list of file paths, or an S3-compatible bucket. Use it the first time you bring an existing archive onto Swarmfile, rather than dragging everything through your mounted drive by hand: it talks to the hub directly rather than through a mount, uploads files concurrently, and resumes from a local state database if the run is interrupted.

Bringing a **git repository** rather than a file tree? Use [`swarmfile git import`](https://swarmfile.com/docs/cli/swarmfile#git-import) instead - it carries the commit history, branches and tags. `swarmfile-migrate` moves files, not version-control history.

![Importing an existing NAS library: one command reads the share, verifies every file by content, and the library appears as an ordinary drive on another machine.](https://swarmfile.com/demo/nas-migration.gif)

This page is a practical walkthrough. `swarmfile-migrate` is installed on `PATH` with the desktop app on every platform. For the complete flag reference, see [swarmfile-migrate](https://swarmfile.com/docs/cli/swarmfile-migrate).

## A realistic example

Importing a local project directory, skipping cache and scratch files:

```bash
swarmfile-migrate --source /Volumes/nas/ProjectArchive \
  --hub-url https://hub.swarmfile.com \
  --org-id acme-films --project-id feature-01 \
  --exclude "*.cache" --exclude "**/tmp/**"
```

This walks the source directory, applies the gitignore-style exclude patterns to skip anything you don't want copied, and uploads the rest into the target project.

## What to expect while it runs

Migrate reports progress as it goes and retries failed transfers automatically, with backoff, up to 3 attempts by default (`--retry`) - a dropped connection partway through a large file doesn't fail the whole run, it retries that transfer. If the process itself is interrupted (you kill it, the machine sleeps, the network drops entirely), it's safe to just run the same command again - a file that had exhausted its retries in the earlier run is still eligible on the next invocation.

## Resume

Migrate keeps a local state database tracking what's already been uploaded. On a second run with the same source and target, it picks up where it left off instead of re-uploading everything from scratch. You don't need a separate `--resume` step or flag - re-running the same invocation is the resume mechanism.

## Verification

After each file uploads, migrate checks its content against the source - a CID/hash comparison - so a successful run means the data landed intact, not just that bytes were sent. This is on by default; pass `--verify=false` to skip it if you trust the transport and want to roughly halve I/O on a very large migration. Migrate can also produce a JSON report of the run, which is the artifact to keep if you need to audit exactly what was migrated, skipped, or retried.
