The status walk problem
git status compares working tree to index, walking every tracked file's stat info. On a million-file repo this can take seconds. Fsmonitor uses the operating system's file change notifications (FSEvents on macOS, ReadDirectoryChangesW on Windows, inotify on Linux) to know which files changed since the last query, skipping the rest.
Built-in daemon (Git 2.36+)
git config core.fsmonitor true
git fsmonitor--daemon start
git fsmonitor--daemon status
git fsmonitor--daemon stop
The daemon launches automatically on first use; you rarely need to start it by hand.
External integrations
Before the built-in daemon, Git supported external hooks:
git config core.fsmonitor /path/to/hook
git config core.fsmonitorHookVersion 2
Watchman (Facebook's file-watching service) is a popular choice. The Watchman query hook ships with Git's contrib directory.
Verifying
GIT_TRACE2_PERF=1 git status 2>&1 | grep fsmonitor
git fsmonitor--daemon status
git update-index --fsmonitor
Untracked cache
Pair fsmonitor with the untracked cache for the full speedup:
git config core.untrackedCache true
Without it, Git still scans the working tree for untracked files even when fsmonitor flagged none.
Performance numbers
On a 4-million-file monorepo, git status drops from 5+ seconds to under 200ms. On a 100k-file repo, from 800ms to 30ms. The bigger the tree, the bigger the win.
Common mistakes
Enabling fsmonitor without untracked cache — only half the win. Running on a network filesystem that does not support change events; fsmonitor will silently fall back. Restarting Git after upgrading without restarting the daemon: git fsmonitor--daemon stop first. WSL1 lacks proper inotify; WSL2 works correctly.
Caveats per platform
- macOS: FSEvents is reliable, the built-in daemon is preferred.
- Windows: ReadDirectoryChangesW; works well on NTFS, less reliable on network drives.
- Linux: inotify limits (
fs.inotify.max_user_watches) may need raising for huge trees.
sudo sysctl fs.inotify.max_user_watches=524288
Related
See "Fsmonitor daemon mode (Git 2.36+)", "Git in a monorepo", and "Configuring index.version for performance".