fix(repo): a committed node_modules symlink pointed every clone at one machine - #454
Conversation
…e machine `development` tracks `node_modules` as a mode-120000 symlink to `/home/rubenlinde/nextcloud-docker-dev/workspace/server/apps-extra/decidesk/node_modules` — one developer's absolute path, on one machine. Anywhere else that is a dangling link sitting exactly where npm expects a directory. I put it there. It rode in on `git add -A` in #452 (`3511f0f6`, `A node_modules`), and it was the only unintended entry in that commit. WHY .GITIGNORE DID NOT CATCH IT `.gitignore` said `/node_modules/`. A pattern ending in `/` matches a DIRECTORY only. The thing added was a SYMLINK, so the rule did not apply to it and it went straight into the index. Proven both directions on this tree: with the old pattern: git check-ignore -v node_modules -> no match with the new pattern: git check-ignore -v node_modules -> .gitignore:19:/node_modules So the fix is not only to untrack the link but to close the hole: `/node_modules` and `/website/node_modules` lose their trailing slashes, which makes them match a directory AND a symlink. The comment above them says why, because the next person to "tidy up" that pattern will want to put the slash back. This is a foreseeable hazard rather than bad luck: pointing a git worktree at a sibling checkout's install is the normal way to avoid a second 534 MB `node_modules`, and it produces exactly this symlink in a tree where `git add -A` will take it. Untracking it does not delete anyone's local install — the link stays on disk and is now ignored. Scope: `.gitignore` plus removing the tracked entry. No source file is touched, so no gate and no test can move.
|
Merging with evidence — the one red check is provably not this change. quality / E2E Tests (Playwright): fail — identical to the base.
This change touches Every other check on this PR is green, including Hydra Gates. |
Quality Report — ConductionNL/decidesk @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| composer | ✅ | ✅ 100/100 | |||
| npm | ✅ | ✅ 548/548 | |||
| PHPUnit | ✅ | ||||
| Newman | ✅ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ✅ |
Quality workflow — 2026-08-11 09:22 UTC
Download the full PDF report from the workflow artifacts.
developmenttracksnode_modulesas a mode-120000 symlink to/home/rubenlinde/nextcloud-docker-dev/workspace/server/apps-extra/decidesk/node_modules— one developer's absolute path, on one machine. Anywhere else that is a
dangling link sitting exactly where npm expects a directory.
I put it there. It rode in on
git add -Ain #452 (3511f0f6,A node_modules),and it was the only unintended entry in that commit.
WHY .GITIGNORE DID NOT CATCH IT
.gitignoresaid/node_modules/. A pattern ending in/matches a DIRECTORYonly. The thing added was a SYMLINK, so the rule did not apply to it and it went
straight into the index. Proven both directions on this tree:
with the old pattern: git check-ignore -v node_modules -> no match
with the new pattern: git check-ignore -v node_modules -> .gitignore:19:/node_modules
So the fix is not only to untrack the link but to close the hole:
/node_modulesand
/website/node_moduleslose their trailing slashes, which makes them match adirectory AND a symlink. The comment above them says why, because the next person
to "tidy up" that pattern will want to put the slash back.
This is a foreseeable hazard rather than bad luck: pointing a git worktree at a
sibling checkout's install is the normal way to avoid a second 534 MB
node_modules, and it produces exactly this symlink in a tree wheregit add -Awill take it.
Untracking it does not delete anyone's local install — the link stays on disk and
is now ignored.
Scope:
.gitignoreplus removing the tracked entry. No source file is touched, sono gate and no test can move.
Verification
Introduced by me in #452. Reported by no gate — gate-29 (gitignore-then-commit) asks the inverse question (does this change add an ignore rule over already-tracked files), and it is diff-scoped, so nothing was watching this direction.
🤖 Generated with Claude Code