Skip to content
Latchkey

rsync --exclude / --include: Filtering Files

rsync --exclude skips files matching a pattern; --include re-adds files an exclude would have dropped.

CI deploys almost always need to exclude build junk like node_modules or .git. The catch is that include/exclude order matters: first match wins.

What it does

rsync evaluates filter rules top to bottom and uses the first matching rule for each file. --include re-includes a file before a broader --exclude can drop it, which is why includes generally come first. Patterns without a leading slash match at any depth; a leading slash anchors to the transfer root.

Common usage

Terminal
# Exclude build junk from a deploy
rsync -av --exclude='.git/' --exclude='node_modules/' ./ user@host:/srv/app/

# Include only .js and .css, exclude everything else
rsync -av --include='*/' --include='*.js' --include='*.css' \
  --exclude='*' src/ user@host:/srv/assets/

Filter options

FlagWhat it does
--exclude=PATTERNSkip files matching the pattern
--include=PATTERNRe-include files an exclude would drop
--exclude-from=FILERead exclude patterns from a file
--include-from=FILERead include patterns from a file
--filter=RULEGeneral filter rule (merge, dir-merge, etc.)
-C / --cvs-excludeAuto-exclude common VCS and editor cruft

In CI

When using an include-only pattern (--include then --exclude="*"), you must also --include="*/" so rsync descends into subdirectories. Without it, rsync excludes the directories themselves and never reaches the files you wanted to keep.

Common errors in CI

A frequent surprise is that nothing transfers: with --exclude="*" listed before your --include rules, the first-match-wins logic excludes everything. Reorder so includes precede the catch-all exclude. Trailing-slash patterns like "node_modules/" match directories only.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →