Why can a build context still carry a file whose name appears in the build's ignore rules?
answer
- a written rule is not a matched rule
- no warning for a rule matching nothing
- anchoring at root or any depth
- rules belong to the context root
- later re-inclusion can undo an exclusion
basics
~20 sBecause a rule that is written is not a rule that matched. It can be anchored differently than assumed, be a pattern that matches nothing at all, be undone by a later re-including rule, or belong to a context root that this particular invocation did not use.
solid answer
~50 sIgnore rules fail silently: nothing reports a rule that never matched, so the file reads as excluded and is packaged anyway. Four causes cover almost every case. **Anchoring** — a bare name may be matched only at the context root, or at any depth, and dialects genuinely differ, so a nested copy slips through. **A pattern that matched nothing** — a typo, the wrong case, a trailing separator, or a path written relative to the wrong root. **Order and re-inclusion** — where the syntax supports negation, a later broad re-include can undo an earlier exclusion. **The wrong root** — the rules are a property of the context root, so an invocation pointed at a different directory does not pick up the rules file sitting at the first one. The check is always the same: ask the builder what it packaged instead of re-reading the rules.
code
pseudocode · 11 linesrule = "secrets" # written as a bare name
candidate = "components/reporting/secrets/signing-key"
matched = path_matches(rule, candidate)
# false when the matcher anchors rules at the context root
# true when it matches the name at any depth
# designs differ, so treat this as untested until you check
if not matched:
package candidate into the bundle # this branch fires here
# the rules file still reads as if the key were excludedgo deeper
The takeaway is that writing an ignore rule and having it match are different things, and nothing tells you when it did not match. Check what was packaged rather than trusting the file.
Name the mechanisms behind the misses: anchoring, a pattern that matched nothing, order with re-inclusion, and rules read relative to a context root the build did not use.
Demonstrate the verification order — context size first to catch rules doing nothing, then the specific path, then repeat per invocation path — and explain why this control is write-only until verified.
The lead's angle is durability: few, directory-level rules, one deliberately chosen context root per build, and a habit of re-verifying when the tree's shape changes, so the control does not quietly decay across teams.
## Why this failure is silent Every other part of a build is loud. A missing file fails a copy; a failed command fails the step. The ignore rules are the exception: a rule that matches nothing behaves exactly like a rule that was never written, and nothing warns you. So the rules file becomes a statement of *intent* that people read as a statement of *fact*, and the gap between the two is where oversized contexts and leaked files live. ## The four ways rules miss **1. Anchoring.** The single most common cause. You wrote a bare directory or file name, and the matcher may interpret it as "this path relative to the context root" or as "this name at any depth" — designs genuinely differ on this, and so do people's assumptions about the one they use. A rule that excludes the copy at the root leaves the nested copy under a component directory in the set. The same applies to leading and trailing separators and to whether a pattern's wildcard crosses directory boundaries. **2. The pattern matched nothing at all.** Mundane and extremely common: - a typo or a plural that does not exist on disk; - a case difference on a case-sensitive filesystem, written on a machine where case did not matter; - a path written relative to the repository root when the context root is a subdirectory, or vice versa; - a directory that was renamed, leaving a rule pointing at a name nothing uses any more. **3. Order and re-inclusion.** Where the syntax supports negated rules, the rules are a sequence, not a set: a later broad re-inclusion can bring back paths an earlier rule excluded. Reading the file top-down and stopping at the line that looks right is how this one gets missed. **4. The rules belong to a root this build did not use.** The rules are read relative to the **context root**, not to the project. Point a build at a parent directory, or at a sibling component, and the rules file you were relying on may not be at that root at all — so an invocation that looks equivalent produces a completely different set. A second build path that assembles its own context is the same story with a different cause. ## Verify the set, not the file | what you check | what it tells you | what it misses | |---|---|---| | re-reading the rules file | what you intended to exclude | every one of the four failures above | | the size the builder reports for the context | whether the rules are doing anything at all | which specific path slipped through | | the packaged set listed and searched for the path | the actual answer for this invocation | nothing, for this invocation | | the same check for each invocation path | whether every caller gets the same set | a caller nobody knew about | The ordering is deliberate: size first because it is cheap and catches the "rules do nothing" case immediately, then the specific path, then repeat for each way the build is invoked. A tree of 2 GB producing a context of 1.9 GB tells you in one glance that the rules never engaged. ## How to keep the rules honest over time - **Prefer excluding directories over enumerating file patterns.** One rule for a generated-output directory is more durable than five patterns for the kinds of file it contains. - **Keep the number of rules small enough to read.** A long list with negations in it is where order bugs hide, and nobody re-derives it in review. - **Treat a rule as untested until you have seen the set without the path.** Write the rule, then confirm the exclusion the same way you would confirm any other change. - **Have one context root per build, deliberately chosen.** Most "the rules did not apply" incidents are really "this invocation used a different root". - **Re-verify when the tree's shape changes.** A new component directory, a rename or a moved fixture can un-match a rule that worked for a year. ## What to say in the interview The strong answer is not a list of syntax caveats; it is the recognition that this control is **write-only unless you verify it**, plus the four causes and the verification order above. A candidate who says "the rule is there, so the file is excluded" is describing the exact belief that ships the file.
- How do you prove an exclusion actually worked?Look at the set the build produced, not the rules. Compare the size the builder reports for the packaged context against the size of the tree — a near-match means the rules did nothing — and then confirm the specific path is absent. Repeat for every way the build is invoked.
- The rules worked for a year and then stopped. What changed?Usually the tree's shape, not the rules. A directory was renamed, a component was added with its own nested copy of an excluded name, a fixture moved, or a second invocation started pointing at a different context root. All four un-match a rule without touching it.
- Are ignore rules the same thing as the version-control system's ignore file?No, and conflating them is a classic gap. They are separate mechanisms with separate files and separate matching behaviour, and neither is consulted by the other. A file can be untracked by version control and still be packaged into the build context, which is exactly how local artifacts get sent.
saying these in an interview costs you the question
- The rule is in the file, so the file is definitely excluded.
- Ignore rules and the version-control ignore file are the same mechanism.
- A rule that matches nothing produces a warning you would have noticed.
- Rules apply to the whole repository, whatever root the build was pointed at.
- A bare directory name always matches that directory at every depth.
- Rule order never matters, because the rules are just a set of exclusions.