Skip to content

feat(desktop): warn about tracked files that match .gitignore, offer to untrack - #264

Merged
devlint merged 3 commits into
mainfrom
feat/tracked-ignored-warning
Oct 14, 2026
Merged

devlint merged 3 commits into
mainfrom
feat/tracked-ignored-warning

Conversation

@devlint

@devlint devlint commented Oct 13, 2026

Copy link
Copy Markdown
Owner

Roadmap › Later: "Tracked files matching .gitignore — warn when tracked paths match an ignore rule (git ls-files -ci --exclude-standard) and offer to untrack them (git rm --cached, files kept on disk)."

What

  • Detection: git_tracked_ignored runs git ls-files -z -c -i --exclude-standard. It returns the first 500 paths plus total / truncated.
  • Untrack: git_untrack_paths runs git --literal-pathspecs rm --cached --quiet --ignore-unmatch --pathspec-from-file=- --pathspec-file-nul, with paths on stdin (no argv limit, no glob expansion). Each path goes through safe_repo_path().
  • UI: a small dismissible notice in the changes pane, "N tracked files match .gitignore", with Review and Dismiss. Review opens a checkbox list with "Untrack selected" and "Untrack all". Both go through a confirm dialog that says the files stay on disk and the removal is staged for the next commit. All on BaseModal.
  • Dismissal: stored per repo (localStorage, try/catch), keyed on the set of paths, so the notice comes back when the set changes.
  • When it runs: on repo open, on a manual refresh, and on Live Repo watcher events that touch a .gitignore at any depth or .git/info/exclude, move HEAD, or arrive truncated. Debounced to 400 ms. Never on the 30 s status poll. .git/info/exclude is now classified as config by the watcher; nothing else reacts to that kind.
  • Backend wrappers, commandRegistry entries, dev-server routes, Tauri handlers and parity-probe arms are all added. Strings are in all 5 locales.

Tests

  • Rust (10): a committed file later matched by a new rule, nested .gitignore, .git/info/exclude, untracked ignored files not reported, spaces/unicode/glob characters in names, untrack keeps the file and stages its removal, literal matching, stale and escaping paths, 3000 paths with the 500 cap.
  • Watcher tests: 20 passed.
  • Composable (13).
  • Parity (4).
  • Full desktop vitest: 1953 passed. pnpm test:parity: 136 passed. The first parity run had 4 failures in 3 files (one a snapshot-prune test), right after the full vitest and cargo runs. They were not investigated, and the rerun was fully green. Watch CI.

Notes

  • Needs git ≥ 2.25 (--pathspec-from-file). The app already uses 2.23+ commands.
  • "Untrack all" covers the listed 500 at most; the confirm dialog says so and the notice returns for the rest.
  • A tracked symlink pointing outside the repo is refused by safe_repo_path().
  • core.excludesFile edits are not watched.
  • Not clicked through in the app. Translations need a native read.

@devlint
devlint force-pushed the feat/tracked-ignored-warning branch from 4a1af79 to dd6eb5a Compare October 14, 2026 07:42
@devlint
devlint merged commit 4b43af0 into main Oct 14, 2026
9 checks passed
@devlint
devlint deleted the feat/tracked-ignored-warning branch October 14, 2026 07:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant