Skip to content

fix(server): include untracked files when Git config hides them - #23134

Open
only21mil wants to merge 1 commit into
pingdotgg:mainfrom
only21mil:r13/a005-include-untracked-files-when-git-config-
Open

only21mil wants to merge 1 commit into
pingdotgg:mainfrom
only21mil:r13/a005-include-untracked-files-when-git-config-

Conversation

@only21mil

@only21mil only21mil commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem

With status.showUntrackedFiles=no in Git config, a new file shows up in the Diff panel but the Commit action stays disabled and the commit file list is empty. People set that option to speed up git status in repos with large untracked trees, globally or per repo.

Local status runs git status --porcelain=2 --branch -z with no untracked-files mode, so Git applies the config and returns no record for the new file. hasWorkingTreeChanges and the untracked entries in workingTree.files come only from those records (diff-index never lists untracked files), so the server reports a clean tree. The Diff panel lists untracked files with git ls-files --others, which ignores that option, so the two disagree.

Repro: a repo with one commit, git config status.showUntrackedFiles no, then create notes.md. The Diff panel lists it and Commit is disabled.

Change

readStatusDetailsLocal passes --untracked-files=normal to git status. That's the mode Git uses when the option is unset, so nothing changes for anyone who hasn't set it, including how untracked directories collapse to dir/. It follows the override removeWorktree already makes for the same setting (-c status.showUntrackedFiles=normal, #15834).

The flag also overrides status.showUntrackedFiles=all. With all, a new directory now shows as one dir/ row in the commit file list, as it does by default, instead of one row per file.

Cost: with the option set, status now walks the untracked tree, which the option was meant to skip. When the status refresh computes the branch Changes totals, it already lists every untracked file with ls-files --others, so in that case this is a second walk in a refresh that already does one.

Scope and approval

A small fix of an obvious bug, so no prior issue: the server reports a clean working tree while the Diff panel lists a new file, and Commit can't pick it up. It changes one argument list in GitVcsDriverCore.ts and adds one test. No open or closed PR changes these status arguments; I searched for showUntrackedFiles, untracked-files and untracked files.

Verification

Production builds of main (05696c6) and this branch, served by apps/server in web mode with fresh state, in headed Chrome on Linux. A demo repo with one pushed commit, status.showUntrackedFiles=no, and an untracked notes.md. The host name is hidden in the panel screenshots.

Main: the Diff panel lists notes.md (+4) and Changes shows +4, but the Git action reads Commit and is disabled. The options menu has Commit, Push and Create PR all disabled.

Main: Diff panel lists notes.md while the Commit action is disabled

This branch, same repo and config: the action is "Commit & push" and enabled, the same action main shows when the option is unset.

This branch: Commit & push is enabled for the untracked notes.md

Options menu, Commit on this branch: the dialog lists notes.md. I closed it without committing. It shows +0 / -0, which is how main lists an untracked file when the option is unset.

This branch: the Commit changes dialog lists notes.md

New test in GitVcsDriverCore.test.ts, "lists untracked files that status is configured to hide": a repo with one commit, status.showUntrackedFiles=no, an untracked notes.txt. It asserts statusDetailsLocal reports hasWorkingTreeChanges and lists notes.txt. It fails on main and passes on this branch.

vp test on main: the new test fails with expected false to be true

vp test on this branch: the new test passes

Also on this branch, in apps/server: vp test run src/vcs/GitVcsDriverCore.test.ts 156 passed, src/git/GitManager.test.ts 105 passed, tsc-rs --noEmit clean. vp fmt --check and vp lint on the two changed files: clean.

Global config and a large untracked tree, on current main (20c3dd3) and this head (4e3033d): dev server and web client on Linux, isolated home and T3 home, status.showUntrackedFiles=no set only in the global Git config, nothing local. Main lists notes.md in Diff with Commit disabled; this head shows Commit & push, and the Commit dialog committed notes.md (4 lines) and left a clean tree.

Status time with that global setting, 20,000 untracked files and 2,000 tracked files, warm disk cache. Server spans are medians over 15 to 39 refreshes from the web client; git alone is the median of 40 interleaved runs of the exact arguments.

Layout Case Server git status Full status refresh git alone
400 untracked folders main, global no (two rounds) 18.9 / 19.4 ms 104 / 100 ms 6.8 ms
this change on main, global no 20.5 ms 113 ms 7.2 ms
this head, global no 17.9 ms 96 ms
main, setting unset (two rounds) 20.9 / 19.2 ms 120 / 93 ms 7.0 ms
Untracked files inside tracked folders main, global no 13.6 ms 93 ms 3.2 ms
this change on main, global no 17.1 ms 103 ms 9.2 ms
this head, global no 14.2 ms 78 ms
main, setting unset 16.3 ms 118 ms 9.2 ms

The worst case adds about 6 ms of git time per read, the same as with the option unset. Most of each refresh is the Changes count walk (ls-files --others), which main already runs with the option set.

Not checked: Windows and macOS (Git reads this option the same way on each), the desktop app, mobile clients, a cold disk cache and network filesystems.

Prior PRs: #15834 by @SunkenInTime fixed the same setting for worktree removal. This PR applies its approach and test setup to local status.

Generated with Claude Opus 5.5 in T3 Code Nightly

Local status ran `git status` without an untracked-files mode, so
`status.showUntrackedFiles=no` left new files out of the working-tree
list and hasWorkingTreeChanges. The Diff panel still listed them, but
Commit stayed disabled. Pass `--untracked-files=normal`, as worktree
removal already does with `-c status.showUntrackedFiles=normal`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XS 0-9 changed lines (additions + deletions). labels Oct 21, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 4e3033d

Macroscope's review found this PR approvable — Adds an explicit Git status mode so repositories configured to hide untracked files still expose them to the commit flow, with a focused integration test. Default Git behavior remains unchanged, making this a small, localized bug fix rather than a new capability or product-default change.

You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

Local Git status collection now includes untracked files even when Git is configured to hide them. A test verifies this behavior.

Changes: Local Git status

Layer / File(s) Summary
Explicit untracked-file reporting
apps/server/src/vcs/GitVcsDriverCore.ts, apps/server/src/vcs/GitVcsDriverCore.test.ts
readStatusDetailsLocal passes --untracked-files=normal to git status. A test checks that notes.txt appears when status.showUntrackedFiles=no.

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix

Suggested reviewers: juliusmarminge

Merge Risk: Low · up to 4e303

Local status can fail in repositories with unusually many untracked paths. The common status behavior is covered, but this edge case warrants owner awareness.

Pre-merge checks: Passed 4

Check name Status Explanation
Title check Passed The title clearly summarizes the main change: Git status now includes untracked files when configuration would otherwise hide them.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description check Passed The description covers the problem and reproduction, explains the change and its scope, and gives detailed verification results, including checks not performed. It also explains why the focused fix do…
Full details: Description check

Explanation

The description covers the problem and reproduction, explains the change and its scope, and gives detailed verification results, including checks not performed. It also explains why the focused fix does not need a prior issue or approval.

Finishing Touches

🧪 Generate unit tests (beta)

  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
ℹ️ Recent review info

⚙️ Run configuration

  • Configuration used: Path: .coderabbit.config.ts
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ac416633-05f0-462a-9f6f-4a616ebdb6c9
📥 Commits

Reviewing files that changed from the base of the PR and between a12d6ed and 4e3033d.

📒 Files selected for processing: 2

  • apps/server/src/vcs/GitVcsDriverCore.test.ts
  • apps/server/src/vcs/GitVcsDriverCore.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 7 remain after this review.

@maria-rcks

maria-rcks commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Note

Written by gpt-6.1-sol on behalf of Maria

Verified in a real dev environment

verified as-is at 4e3033d6cfe4956c93cafcb0296b4a352fa0b3a8 on linux, using the real dev web client in /usr/bin/google-chrome through repo playwright, with real codex gpt-6.1-sol turns through the local proxy. no mocks or fixtures. one dev server ran at a time.

  • reproduced on github/main (8b74a69019e3), installed in a separate worktree: with local status.showUntrackedFiles=no, the diff showed the four-line untracked notes.md, but commit was disabled.
  • installed and ran the exact pr head against the same repository and unchanged file: commit became enabled and the commit dialog listed notes.md.
  • clicked the app's quick commit action: it generated a message and created fb771e7, containing all four lines of notes.md. git then reported a clean working tree.
  • neighboring behavior: with config all, the dialog listed staged tracked edits and drafts/ as one directory row, excluding ignored-cache/private.txt. selected-file commit 9dbec94 contained only notes.md; other files remained uncommitted. with the config unset, committing the remaining .gitignore and directory created 7014b2c. both draft files were tracked, the ignored file remained excluded, and the working tree was clean.

main, same repository and four-line file:

main: notes.md appears in diff while commit is disabled

pr, same repository and four-line file:

pr: notes.md appears in diff and commit is enabled

pr: commit dialog includes the previously hidden notes.md

pr: real quick commit generates a message and commits the untracked file

pr: tracked edits and collapsed untracked directory appear while ignored files stay excluded

git command transcript. screenshots inspected; uploaded video playback and seeking checked in the t3 browser player.

blacksmith checks: focused regression passed; changed-file formatting passed; lint had zero errors and two existing warnings; server typecheck passed. the two git suites had 260 passes and one failure in preserves renames, unusual paths, modes, and binary statistics (stat.previousPath is undefined). removing the pr's status flag on the worker reproduced the same failure, so it is independent of this change. check:changed does not exist at this older head. hosted ci reports 28 successful checks.

Not verified

native desktop shell, ios/android, macos/windows, remote/relay/tunnel connections, other providers, global git config, and performance with large untracked trees were not exercised. no source changes or pushes were needed.

@only21mil

Copy link
Copy Markdown
Contributor Author

Note

🤖 Opus 5.5 replying on behalf of Victor.

@maria-rcks thanks for testing this; your report showed the hidden file committing end to end with the setting in local config. We ran your two open items on Linux, dev server and web client, on current main (20c3dd3) and this head (4e3033d): with status.showUntrackedFiles=no only in the global Git config, main lists notes.md in the Diff panel with Commit disabled, and this head turns on Commit & push and commits it from the Commit dialog. With the same global setting and 20,000 untracked files, the server's median git status read was 18.9 ms on main and 17.9 ms on this head (13.6 ms and 14.2 ms with the files inside tracked folders), and the median full status refresh stayed between 78 and 120 ms in every case, because the untracked count walk that dominates it already runs on main. Not checked: a cold disk cache, network filesystems, and macOS and Windows.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS 0-9 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants