-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Functions emulator file watcher silently ignores changes in git worktrees #10187
Description
[REQUIRED] Environment info
firebase-tools: 15.9.0
Platform: macOS (Darwin 25.2.0)
[REQUIRED] Test case
The Functions emulator's chokidar file watcher is configured with a regex to ignore hidden (dot-prefixed) directories:
// lib/emulator/functionsEmulator.js — line ~270
const watcher = chokidar.watch(backend.functionsDir, {
ignored: [
/.+?[\\\/]node_modules[\\\/].+?/,
/(^|[\/\\])\../, // <-- matches .worktrees in absolute path
/.+\.log/,
/.+?[\\\/]venv[\\\/].+?/,
...(backend.ignore?.map((i) => `**/${i}`) ?? []),
],
persistent: true,
});Chokidar tests this regex against absolute file paths. When the project is in a git worktree, every path contains /.worktrees/, which matches /(^|[\/\\])\../ at the /.w position:
/Users/dev/project/.worktrees/my-feature/functions/lib/index.js
^^^^^^^^^^
matches /(^|[\/\\])\../
This causes every file change event to be silently dropped.
[REQUIRED] Steps to reproduce
- Create a git worktree:
git worktree add .worktrees/my-feature cd .worktrees/my-feature- Start the Functions emulator
- Observe the emulator logs — you should see
Watching "<path>" for Cloud Functions...confirming the watcher is set up - Edit a function source file and save
- Observe that the emulator never reloads — no
Loaded functions definitions from sourcemessage appears
[REQUIRED] Expected behavior
The Functions emulator should detect file changes in the functions source directory and reload triggers, regardless of whether the project is inside a git worktree (.worktrees/) directory. After saving a file change, the emulator should log Loaded functions definitions from source: ... and serve the updated code.
[REQUIRED] Actual behavior
All file change events are silently ignored by chokidar because the absolute path contains /.worktrees/, which matches the hidden directory regex /(^|[\/\\])\../. The emulator continues serving stale code with no error or warning. The change event listener and loadTriggers reload mechanism work correctly — the issue is purely that the ignored regex prevents chokidar from ever firing events.
This can be confirmed in a Node REPL:
const re = /(^|[\/\\])\../;
re.test("/Users/dev/project/.worktrees/feature/functions/lib/index.js");
// → true (matched "/.w" in "/.worktrees")Suggested Fix
Add a negative lookahead to exclude .worktrees from the hidden directory pattern:
// Before:
/(^|[\/\\])\../
// After:
/(^|[\/\\])\.(?!worktrees[\/\\])/This preserves the intent of ignoring hidden directories (.git, .cache, etc.) while allowing git worktree paths to function correctly.