FreeFileSync Exclude Folders on Mac: A Developer’s Guide

FreeFileSync exclude folders guide for Mac developers: skip node_modules, .git, venv, caches, and build output for cleaner backups.

Mac developer frustrated by a folder sync job copying dependency files and build caches

Search for FreeFileSync exclude folders after a slow Mac sync and you are probably trying to solve one specific problem: the tool is doing exactly what you asked, but your project folder contains things you never meant to copy. A JavaScript app may have 80,000 files in node_modules. A Python service may hide a whole interpreter under .venv. A Rails app may carry vendor/bundle, logs, temp files, and compiled assets. If those folders enter your sync job, even a good sync tool starts wasting time.

FreeFileSync exclude folders on Mac: start with the generated stuff

FreeFileSync is useful when you want a visual way to compare two folders, preview changes, and run a repeatable sync. It is not the problem. The problem is that developer folders do not behave like document folders. A normal documents folder has files you created and probably want to keep. A codebase has source files mixed with generated state that can be rebuilt from lockfiles, package managers, compilers, and test runners.

That difference matters. Syncing src/, package.json, pnpm-lock.yaml, migrations, docs, and scripts gives you a useful backup. Syncing node_modules/, .git/objects/, .next/cache/, coverage/, .venv/, and tmp/ gives you a larger, slower, noisier copy. Sometimes it also gives you a worse restore, because caches and local binaries can be stale, machine-specific, or half-written during the sync.

Why FreeFileSync gets slow on code folders

Sync tools spend time on file count, not just total bytes. A single 2 GB video file is boring to scan compared with 100,000 tiny files spread across nested dependency folders. Each file needs metadata checks. Depending on the settings, the tool may compare size, modification time, permissions, and sometimes content. macOS may also trigger Spotlight indexing, file provider events, antivirus scans, external drive metadata writes, or iCloud Drive uploads on the destination side.

node_modules is the famous case because npm packages contain source files, transpiled builds, type definitions, package metadata, nested dependencies, binaries, tests, maps, and license files. But the same pattern appears in every stack:

  • Python: .venv/, venv/, __pycache__/, .pytest_cache/, dist/, build/.
  • Ruby: vendor/bundle/, tmp/, log/.
  • Java and Kotlin: target/, build/, .gradle/.
  • Frontend frameworks: .next/cache/, .nuxt/, dist/, coverage/, .turbo/.
  • Git: .git/, especially large object stores and packed history.
Filter before the compare phase gets expensive Project folder src/ package.json README.md node_modules/ .git/ .venv/ Excludes skip churn Backup mirror src/ package.json README.md fewer files to scan easier to verify Exclusions keep FreeFileSync focused on durable project files instead of package-manager churn.
Put the filter in front of the expensive part. If generated folders never enter the comparison, the sync has less work to do and fewer weird files to copy.

Basic FreeFileSync exclude patterns for Mac projects

In FreeFileSync, folder filtering lives in the filter settings for the job. The exact UI can change between releases, but the model is stable: include what you want, exclude what you do not want. For developer folders, start with broad directory names before you get clever.

*/node_modules/*
*/.git/*
*/.venv/*
*/venv/*
*/vendor/bundle/*
*/.next/cache/*
*/.nuxt/*
*/dist/*
*/build/*
*/coverage/*
*/__pycache__/*
*/.pytest_cache/*
*/.mypy_cache/*
*/.ruff_cache/*
*/target/*
*/tmp/*
*/log/*
*/.DS_Store

The leading */ is there because these folders may appear inside many projects, not just at the top level. If your source folder is ~/Developer, you want to skip ~/Developer/app-a/node_modules, ~/Developer/app-b/node_modules, and any nested example app that carries its own dependencies.

Be more careful with dist/ and build/. In most app projects those folders are generated output. In some repos, a folder named dist contains published assets you intentionally keep under version control. Treat the list above as a starting point, then preview the comparison before you run the sync.

Abstract sync pipeline clogged by thousands of tiny dependency and cache files
The slow part is usually not your app code. It is the disposable file tree around the app code.

How to test FreeFileSync excludes safely

Do not trust a filter until you have seen the preview. A good safe workflow looks like this:

  1. Create or open the FreeFileSync job for your source and destination folders.
  2. Add the exclude patterns for dependency folders, Git internals, caches, and build output.
  3. Run the comparison, but do not sync yet.
  4. Search the preview for node_modules, .git, .venv, dist, and build.
  5. If the preview still shows generated folders, fix the pattern and compare again.
  6. Run the first real sync to an empty test destination, not your only backup.

That last step sounds fussy, but it catches mistakes. If your destination ends up with source files and lockfiles but not dependencies, the filter is doing its job. If the destination is almost as large as the source, you probably missed a heavy folder. Use Finder's Get Info, du -sh, or a disk usage tool to compare sizes.

du -sh ~/Developer/my-app

du -sh /Volumes/Backup/my-app

The destination should not always be tiny. Repos with images, datasets, or large fixtures can be legitimately large. But if your backup grows by gigabytes after npm install, your exclude list is not catching the right folders.

Mirror vs two-way sync for code folders

FreeFileSync can handle different sync directions. For developer backups, the safest default is usually a one-way mirror from the working folder to the backup folder. Your working folder is the source of truth. The destination is a recoverable copy.

Two-way sync is tempting if you move between two Macs or edit code on an external SSD. It can work, but it makes generated files more dangerous. Package managers and build tools mutate files without you thinking about it. If both sides change, the sync tool has to decide what to do with conflicts. That is fine for a handful of documents. It is annoying inside node_modules, cache directories, SQLite files, test output, and framework internals.

Use a mirror when You want a clean backup of the working folder and the destination should never be edited by hand.
Use two-way sync only when Both folders are active working copies, you review conflicts, and generated folders are excluded aggressively.

Git should still handle source history. A folder sync job is a backup and convenience layer. It is not a replacement for commits, branches, remote repos, and a tested restore process.

When rsync is a better fit than FreeFileSync

If you are comfortable in Terminal, rsync is still hard to beat for scripted one-way sync. It is explicit, easy to automate, and works well with an exclusion file.

# ~/.config/dev-sync-excludes.txt
node_modules/
.git/
.venv/
venv/
vendor/bundle/
.next/cache/
.nuxt/
dist/
build/
coverage/
__pycache__/
.pytest_cache/
target/
.DS_Store
rsync -av --delete \
  --exclude-from ~/.config/dev-sync-excludes.txt \
  ~/Developer/my-app/ /Volumes/Backup/my-app/

Always test destructive mirrors with -n first:

rsync -avn --delete \
  --exclude-from ~/.config/dev-sync-excludes.txt \
  ~/Developer/my-app/ /Volumes/Backup/my-app/

The tradeoff is maintenance. Scripts need logging, scheduling, notifications, and error handling. You need to notice when the external drive was not mounted or when the destination path changed. FreeFileSync gives you a visual preview. rsync gives you a powerful command. Neither one magically knows which developer folders are disposable until you tell it.

Clean filtered Mac folder sync workflow creating an organized backup without dependency folders
A calm sync workflow is boring in the best way: source files move, generated junk stays behind, and failures are visible.

Where Lsyncer fits for Mac developer folder sync

If you like FreeFileSync and already have a job that works, keep it. The important part is the filter. Once you find yourself maintaining the same exclusion list across projects, though, a developer-focused Mac sync app starts to make sense.

Lsyncer is built for this specific workflow: sync project folders on macOS while skipping the folders that make generic sync painful. It is designed around common developer exclusions such as node_modules, .git, virtual environments, build output, and caches. You choose the folders, keep the copy local or on a destination you control, schedule runs, and see when the last sync succeeded or failed.

That visibility is the part scripts often miss. A backup job that silently failed three weeks ago is worse than an obvious manual process. Lsyncer does not replace Git, iCloud Drive, Time Machine, or an external SSD. It gives you a filtered mirror between the messy project tree and the cleaner copy you actually want to keep. It is a one-time $19.99 Mac App Store purchase, so it fits the kind of utility work that should not become another subscription.

Start with this list, then adjust it for the project:

  • Always consider excluding: node_modules/, .git/, .venv/, venv/, vendor/bundle/, __pycache__/, .pytest_cache/, .mypy_cache/, .ruff_cache/, .gradle/, target/, .next/cache/, .nuxt/, .turbo/, coverage/, tmp/, log/, .DS_Store.
  • Review before excluding: dist/, build/, public/, fixtures/, uploads/, local database files, and generated documentation. Some projects treat these as artifacts. Others treat them as source.
  • Usually keep: source files, lockfiles, migrations, scripts, docs, config examples, tests, design assets, and any file needed to rebuild the project from a clean checkout.

The restore test is simple: can you copy the synced folder to another Mac, install dependencies, and run the project? For Node.js that might mean npm ci, pnpm install --frozen-lockfile, or yarn install --frozen-lockfile. For Python it might mean recreating the virtual environment and running pip install -r requirements.txt or uv sync. If the answer is yes, you probably synced the right things.

FAQ

What should I exclude from FreeFileSync for a Mac developer project?

Start with node_modules/, .git/, .venv/, venv/, vendor/bundle/, .next/cache/, dist/, build/, coverage/, __pycache__/, .pytest_cache/, target/, logs, temp folders, and .DS_Store. Review dist/ and build/ before excluding them because some projects keep important files there.

Should FreeFileSync copy node_modules?

Usually no. node_modules is large, noisy, and reproducible from package-lock.json, pnpm-lock.yaml, or yarn.lock. Sync the source files and lockfile, then reinstall dependencies on the destination when you need to run the project.

Is two-way sync safe for code folders?

Two-way sync can be safe for source files if you review conflicts, but it is risky for generated folders. Package managers, build tools, test runners, and local databases can change files on both sides. Exclude generated folders aggressively, and keep Git as the source of truth for source code.

Is rsync better than FreeFileSync on Mac?

rsync is better if you want a scriptable one-way mirror with an exclusion file. FreeFileSync is better if you want a visual comparison and manual review before syncing. Both can work well for developer folders if you exclude dependencies, Git internals, virtual environments, caches, and build output.

Can Lsyncer replace FreeFileSync?

Lsyncer can replace FreeFileSync for the specific job of syncing Mac developer folders with built-in exclusions, schedules, status, and failure visibility. If you need broad two-way sync features for many non-developer workflows, FreeFileSync may still be useful. If your main pain is keeping code backups clean without copying dependency junk, Lsyncer is a focused option.