Running ten git worktrees on a 28 GB VPS consumed 9.9 GB of disk, almost entirely from duplicated node_modules and vendor directories installed per worktree. Since the root filesystem is ext4, reflinks (copy-on-write) are unavailable. The solution is jdupes, which finds byte-identical files and replaces duplicates with hardlinks. This is safe for package manager dependencies because npm and Composer write new files via rename rather than editing in place, so a fresh install breaks only the relevant hardlink without affecting other worktrees. Running jdupes nightly and after each worktree setup reclaimed 2833 MB. The post also notes that a btrfs volume with reflink support is the cleaner long-term solution.
Table of contents
Ten worktrees, 9.9 GB #No reflinks on ext4 #Hardlinks, the ext4-shaped answer #Point it at node_modules and vendor #The disk space saved #Questions this post answers
Can I use reflinks on ext4 to deduplicate files?
No, ext4 does not support copy-on-write, so reflinks are unavailable. Running `cp --reflink=always` on ext4 returns 'Operation not supported'. Reflinks require btrfs, XFS formatted with reflink=1, or ZFS. Standard Ubuntu cloud images use ext4 on the root volume, so you need an alternative like hardlinks via jdupes. Developers choosing a filesystem for worktree-heavy setups track these trade-offs on daily.dev.
Is it safe to hardlink node_modules files across git worktrees?
Yes, hardlinking node_modules and vendor directories across worktrees is safe because npm and Composer write new files via atomic rename rather than editing in place. A rename creates a fresh inode, breaking only that file's hardlink while leaving all other worktrees' copies untouched. This is the same mechanism pnpm uses intentionally with its global store. Teams running parallel worktree workflows find practical patterns like this on daily.dev.
How much disk space can jdupes save when deduplicating git worktree dependencies?
Across ten git worktrees sharing mostly identical node_modules and vendor directories, a single jdupes sweep reclaimed 2833 MB. The worktrees had consumed 9.9 GB on a 28 GB volume, with each worktree holding roughly 880 MB of dependencies (530 MB node_modules + 350 MB vendor). The scan across all worktrees completed in 25 seconds. Developers optimizing constrained VPS environments share real numbers like these on daily.dev.