What does @IgnoreEmptyDirectories do, and when does ignoring empty directories matter for incremental builds?
answer
- empty dirs count in fingerprint by default
- Git doesn't track empty dirs → CI vs local mismatch
- @IgnoreEmptyDirectories drops them from snapshot
- pairs with @PathSensitive
- don't use if layout-with-empty-dirs matters
basics
~10 s@IgnoreEmptyDirectories tells Gradle to leave empty directories out of an input's fingerprint, so stray or environment-created empty folders don't change up-to-date status or the cache key.
solid answer
~40 sBy default, when fingerprinting a directory-tree input Gradle includes the directory structure, including empty directories. That means an empty folder created by tooling, a checkout, or a previous run can change the input fingerprint and trigger a rerun even though no real content changed. Adding `@IgnoreEmptyDirectories` to the `@InputFiles`/`@InputDirectory` property excludes empty directories from the snapshot, so only files (and non-empty structure) count. This stabilizes up-to-date checks and cache keys across environments that differ only in incidental empty folders — common in CI containers vs. local checkouts, or with VCS that don't track empty dirs uniformly. It pairs naturally with path sensitivity: both are fingerprint-stabilizing levers, one for the path component, one for empty-directory noise.
code
kotlin · 4 lines@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
@get:IgnoreEmptyDirectories
abstract val resources: ConfigurableFileCollectiongo deeper
Know the annotation exists and stops empty folders from triggering reruns.
Explain the default behavior, the CI-vs-local Git mismatch, and how to apply the annotation alongside path sensitivity.
Reason about when ignoring empty dirs is unsafe and combine fingerprint-stabilizing knobs deliberately.
Bake RELATIVE + IgnoreEmptyDirectories conventions into shared task types so teams get stable fingerprints by default.
## Default directory fingerprinting When a task input is a directory tree, Gradle's snapshot walks the tree and records each file's path-view + content hash. Crucially, the **directory structure itself** participates — and by default that includes **empty directories**. So the presence or absence of an empty folder can change the fingerprint. ## Why empty directories cause spurious reruns Empty directories appear and disappear for reasons unrelated to a task's real inputs: - Some VCS (notably Git) don't track empty directories, so a clean CI checkout lacks empty folders that exist locally (or vice versa with `.gitkeep` placeholders). - Build tooling, IDEs, or prior task runs leave behind empty output/temp folders inside an input tree. - Container vs. host filesystems differ in stray directories. If any of these sit inside a fingerprinted input, the task's fingerprint differs between environments and you get cache misses or false 'out-of-date' verdicts — pure noise. ## The annotation `@IgnoreEmptyDirectories` on a directory/file-collection input instructs Gradle to **drop empty directories from the snapshot** entirely. Only files and the structure implied by them remain. After this, two trees that differ solely by empty folders fingerprint identically. ```kotlin abstract class PackageTask : DefaultTask() { @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) @get:IgnoreEmptyDirectories abstract val contentRoot: ConfigurableFileCollection } ``` ## Relationship to path sensitivity Think of fingerprint stabilization as having several orthogonal knobs: - **`@PathSensitive`** — how much of each file's *path* is kept. - **`@IgnoreEmptyDirectories`** — whether *empty directories* are kept at all. - **Normalization (classpath)** — which *entry contents* are kept for classpath inputs. They compose: a robust, cache-friendly input often uses RELATIVE + IgnoreEmptyDirectories so that neither checkout location nor stray empty folders cause misses. ## When it does NOT apply If a task genuinely cares whether an empty directory exists (e.g. it mirrors a directory layout including empty dirs into an output), you must **not** ignore them, or you'll produce wrong output. As always, only stabilize away information the task is truly indifferent to.
- Why does this matter more on CI than locally?Git doesn't track empty directories, so a fresh CI checkout often lacks empty folders that exist in a developer's working tree; without ignoring them the fingerprints differ and the cache misses across the two environments.
- When would ignoring empty directories be wrong?When the task's output depends on the presence of empty directories — e.g. a packaging task that must reproduce empty folders in its archive. Then ignoring them would drop required structure.
saying these in an interview costs you the question
- Claiming empty directories are ignored by default (they are included unless you opt out).
- Treating it as a path-sensitivity mode rather than an orthogonal annotation.
- Applying it blindly to inputs whose semantics include empty-folder layout.