Every time you deploy a website, something wasteful happens. Your deployment tool connects to your server and uploads every single file — the entire codebase, top to bottom. Changed one CSS rule? Here's 10,000 files anyway.

This is how FTP clients work. It's how many CI/CD scripts work when they `rsync` or `scp` a build directory. It's slow, it's bandwidth-heavy, and on shared hosting with transfer limits, it's expensive.

There's a better way: **differential deployment** — uploading only the files that actually changed between your last deployment and the current one.

## How Differential Deployment Works

The concept is straightforward. Your Git repository already knows exactly which files changed between any two commits. A smart deployment tool uses this information to transfer only the delta — this is the core idea behind [incremental deployments](https://www.deployhq.com/blog/what-is-an-incremental-deployment).

```
flowchart LR
    A[Git Push] --> B[DeployHQ receives webhook]
    B --> C[Compare HEAD vs last deployed revision]
    C --> D{What changed?}
    D -->|3 files modified| E[Transfer only 3 files via SFTP/SSH]
    D -->|2 files deleted| F[Remove 2 files from server]
    E --> G[Server updated]
    F --> G
```

Here's what happens under the hood:

1. **You push to your repository.** A webhook fires and notifies your deployment service.
2. **The service compares revisions.** It knows the SHA of the last successful deployment and compares it against the new HEAD. This produces a precise list: files added, modified, and deleted.
3. **Only the diff gets transferred.** Three modified files? Three files get uploaded. Two files deleted in the commit? Two files get removed from the server.
4. **The deployed revision is recorded.** Next time, the comparison starts from this new baseline.

The result: a project with 10,000 files where you changed 3 can become a much smaller deployment. The exact time saving depends on the project, build process, server, and transfer protocol, but transferring less data generally means faster feedback.

## Why This Matters More Than You Think

Differential deployment isn't just a speed optimisation. It has cascading benefits:

**Reduced risk.** Fewer files transferred means fewer opportunities for a corrupted upload or a timeout mid-transfer to leave your server in an inconsistent state. When you're uploading 3 files instead of 10,000, the window for failure shrinks dramatically.

**Lower bandwidth costs.** On metered connections — common with shared hosting or some VPS providers — transferring gigabytes of unchanged files every deployment adds up. Differential deployment can reduce transfer volumes substantially on projects where each change touches only a small part of the output.

**Faster feedback loops.** When deployments take seconds instead of minutes, you can deploy more often. More frequent deployments mean smaller changesets, which means easier debugging when something goes wrong.

**Audit clarity.** When your deployment log shows exactly which 3 files were transferred, it's immediately obvious what changed on the server. Compare that to a full deployment log with 10,000 files — finding what actually changed is a needle-in-a-haystack problem.

## The Technical Mechanism

Not all tools implement differential deployment the same way. There are two primary approaches:

### Git-based comparison (how DeployHQ works)

[DeployHQ](https://www.deployhq.com) stores the deployed Git revision SHA for each server. When a new deployment is triggered, it compares the previous deployed revision with the new revision to produce the file manifest. This handles the normal add, modify, and delete cases without requiring a full upload on every deployment.

This approach handles common edge cases such as:

- **Renamed files** : detected as a delete + add, so the old path is removed and the new path is created
- **File permission changes** : the file is re-uploaded with the updated permissions
- **Binary files** : transferred in full because Git does not produce a useful text diff for them
- **Merge commits** : the comparison accounts for changes introduced by the merged history

### Checksum comparison (how rsync works)

`rsync` takes a different approach: it compares file checksums between source and destination. This works but has drawbacks — it requires running a comparison against every file on the server, which can be slow for large codebases, and it requires `rsync` to be installed on both ends.

## When You Need a Full Deployment

Differential deployment handles most routine changes, but there are scenarios where you need a [full deployment](https://www.deployhq.com/blog/what-is-a-full-deployment) — uploading the entire codebase from scratch:

- **First deployment to a new server.** There's no previous revision to compare against — the full codebase needs to go up.
- **Server files were modified directly.** If someone edited files on the server via SSH, the server state may no longer match the Git history. A full deployment resets it.
- **Deployment infrastructure changed.** New server paths, new directory structure, or switching protocols may require a complete transfer.
- **Build output changes.** If you change your build tool or configuration in a way that affects all output files, a full deployment ensures nothing stale remains.

In [DeployHQ](https://www.deployhq.com/features), forcing a full deployment is a single checkbox when you trigger a manual deploy. You can also configure it per-server in the project settings.

## How Build Commands Interact with Differential Deployment

Here's a nuance that trips people up: if your project uses a [build pipeline](https://www.deployhq.com/blog/what-is-a-build-pipeline), the build runs every time regardless of how many files changed. `npm run build` compiles your entire project whether you changed 1 file or 100.

But here's the key — [DeployHQ](https://www.deployhq.com) runs the build step first, then compares the _output_ against what's on the server. So even if `npm run build` regenerates all files in `dist/`, only the files whose content actually changed get transferred.

This means your build can be comprehensive while your deployment remains surgical.

```
flowchart TD
    A[Git Push: 2 files changed] --> B[Build step runs: npm run build]
    B --> C[Build outputs 500 files to dist/]
    C --> D[DeployHQ compares dist/ against server]
    D --> E[Only 4 files have different content]
    E --> F[4 files transferred to server]
```

## Comparison: Differential Deployment Methods

| Method | How it detects changes | Pros | Cons |
| --- | --- | --- | --- |
| **DeployHQ** | Git revision comparison | Precise, fast, no server-side tooling needed | Requires Git-based workflow |
| **rsync** | File checksum comparison | Works without Git, flexible | Slow for large file sets, needs rsync on both ends |
| **FTP client** | Manual file selection | Simple | Entirely manual, error-prone |
| **GitHub Actions + scp** | Custom scripting | Flexible | Must implement diff logic yourself |
| **Capistrano / Deployer** | Full release directories | Supports rollback | Not truly differential — uploads everything to a new release dir |

## Setting Up Differential Deployment with DeployHQ

If you're currently dragging files into an FTP client or running a CI script that uploads everything, switching to differential deployment takes about 5 minutes:

1. **Connect your Git repository** — GitHub, GitLab, Bitbucket, [Gitea](https://www.deployhq.com/blog/github-actions-ssh-deploy-alternative), or [Codebase](https://www.codebasehq.com)
2. **Add your server** — enter SSH/SFTP credentials and the deployment path
3. **Configure build commands** if your project needs them (e.g., `npm run build`)
4. **Push a commit** — [DeployHQ](https://www.deployhq.com) handles the rest

The first deployment transfers everything because there is no baseline to compare against. Every deployment after that transfers only what changed.

[Automatic deployments](https://www.deployhq.com/features/automatic-deployments) trigger on every push via webhook. No manual steps, no scripts to maintain, no files to forget.

## Frequently Asked Questions

### Does differential deployment require Git?

DeployHQ's differential deployment workflow uses the repository history and deployed revision as its comparison baseline. Other tools can use checksums or timestamps, but their setup and accuracy depend on the tool and server configuration.

### Is the first deployment differential?

Usually not. A new server has no deployed baseline, so the first deployment needs to transfer the files required to create the application. Later deployments can compare the new revision with the last successful deployment.

### When should I trigger a full deployment?

Use a full deployment after changing the deployment path or protocol, recovering from manual server edits, or making a build change that affects the complete output. It is also a sensible recovery step when the server no longer matches the expected deployed state.

* * *

Differential deployment is one of those improvements that seems small until you experience it. Deployments that took minutes can become much faster when only the changed output is transferred. Server inconsistencies from partial uploads are less likely, and the deployment log becomes a precise record of exactly what changed on your server.

Ready to stop uploading 10,000 files when only 3 changed? [Start deploying with DeployHQ](https://www.deployhq.com/signup) — free for one project.

If you have questions about setting up differential deployment for your project, reach out to us at [support@deployhq.com](mailto:support@deployhq.com) or find us on [Twitter/X](https://x.com/deployhq).

