feat(git): add 'default' option to git.untrackedChanges setting#301016
feat(git): add 'default' option to git.untrackedChanges setting#301016murataslan1 wants to merge 1 commit intomicrosoft:mainfrom
Conversation
Add a 'default' option for git.untrackedChanges that reads the value from git's own status.showUntrackedFiles configuration. When the git config is set to 'no', behaves like 'hidden'. Otherwise, behaves like 'mixed'. This enables dotfiles bare repository workflows where status.showUntrackedFiles=no is set in the repo's git config to avoid showing every untracked file in the home directory. Fixes microsoft#249351
There was a problem hiding this comment.
Pull request overview
Adds a new "default" value to the Git extension’s git.untrackedChanges setting so it can follow each repository’s effective status.showUntrackedFiles configuration, improving the dotfiles/bare-repo workflow without forcing a global VS Code setting.
Changes:
- Extends the
git.untrackedChangessetting schema with a new"default"enum value and description. - Adds localization for the new enum description.
- Resolves
"default"insideRepository.getStatus()by readingstatus.showUntrackedFilesand mapping it to"hidden"or"mixed".
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
extensions/git/src/repository.ts |
Adds "default" to the untrackedChanges type and resolves it via git config during status computation. |
extensions/git/package.nls.json |
Adds the localized description string for the new "default" option. |
extensions/git/package.json |
Updates the configuration schema enum/enumDescriptions to include "default". |
| const config = workspace.getConfiguration('git', Uri.file(this.repository.root)); | ||
| const untrackedChanges = config.get<'mixed' | 'separate' | 'hidden'>('untrackedChanges'); | ||
| const untrackedChangesResourceGroupType = untrackedChanges === 'mixed' ? ResourceGroupType.WorkingTree : ResourceGroupType.Untracked; | ||
| const untrackedChanges = config.get<'mixed' | 'separate' | 'hidden' | 'default'>('untrackedChanges'); | ||
| const untrackedChangesResourceGroupType = untrackedChanges === 'mixed' || untrackedChanges === 'default' ? ResourceGroupType.WorkingTree : ResourceGroupType.Untracked; |
There was a problem hiding this comment.
In this optimistic update path, untrackedChanges === 'default' is treated the same as 'mixed' when deciding which resource group untracked files should go to. However, 'default' is later resolved in getStatus() based on status.showUntrackedFiles and can effectively behave like 'hidden', in which case these untracked resources should be omitted (or at least not placed into WorkingTree). Consider reusing the resolved/effective untracked-changes mode (e.g., cache the resolved value from getStatus() on the Repository) instead of branching directly on the raw setting value here, to avoid UI inconsistencies for repos with status.showUntrackedFiles=no.
| // Add resource(s) to working group | ||
| const workingTreeGroup = untrackedChanges === 'mixed' ? | ||
| const workingTreeGroup = untrackedChanges === 'mixed' || untrackedChanges === 'default' ? | ||
| [...this.workingTreeGroup.resourceStates, ...trackedResources, ...untrackedResources] : | ||
| [...this.workingTreeGroup.resourceStates, ...trackedResources]; |
There was a problem hiding this comment.
Same issue as above: this treats 'default' as 'mixed' when computing the optimistic workingTreeGroup. If status.showUntrackedFiles=no, getStatus() will later resolve 'default' to 'hidden' and these untracked resources should not appear at all. Using a cached resolved value (from the last getStatus() run) would keep optimistic updates aligned with the actual status behavior.
| const gitConfig = await this.repository.config('get', '', 'status.showUntrackedFiles'); | ||
| untrackedChanges = gitConfig.trim() === 'no' ? 'hidden' : 'mixed'; | ||
| } | ||
|
|
There was a problem hiding this comment.
getStatus() supports cancellation via cancellationToken, but the extra git config --get status.showUntrackedFiles invocation for the 'default' case doesn't pass that token through. Consider passing { cancellationToken } (and optionally early-checking cancellation again after the config call) so a canceled status refresh can promptly terminate the spawned process.
| const gitConfig = await this.repository.config('get', '', 'status.showUntrackedFiles'); | |
| untrackedChanges = gitConfig.trim() === 'no' ? 'hidden' : 'mixed'; | |
| } | |
| const gitConfig = await this.repository.config('get', '', 'status.showUntrackedFiles', { cancellationToken }); | |
| untrackedChanges = gitConfig.trim() === 'no' ? 'hidden' : 'mixed'; | |
| } | |
| if (cancellationToken && cancellationToken.isCancellationRequested) { | |
| throw new CancellationError(); | |
| } |
| "config.untrackedChanges.mixed": "All changes, tracked and untracked, appear together and behave equally.", | ||
| "config.untrackedChanges.separate": "Untracked changes appear separately in the Source Control view. They are also excluded from several actions.", | ||
| "config.untrackedChanges.hidden": "Untracked changes are hidden and excluded from several actions.", | ||
| "config.untrackedChanges.default": "Use the value of git's `status.showUntrackedFiles` configuration. When set to `no`, behaves like \"hidden\". Otherwise, behaves like \"mixed\".", |
There was a problem hiding this comment.
Consider capitalizing “Git” in this user-facing description (it’s treated as a proper noun elsewhere in the Git extension’s settings descriptions).
| "config.untrackedChanges.default": "Use the value of git's `status.showUntrackedFiles` configuration. When set to `no`, behaves like \"hidden\". Otherwise, behaves like \"mixed\".", | |
| "config.untrackedChanges.default": "Use the value of Git's `status.showUntrackedFiles` configuration. When set to `no`, behaves like \"hidden\". Otherwise, behaves like \"mixed\".", |
Summary
Fixes #249351 — Adds a
defaultoption togit.untrackedChangesthat reads from git's ownstatus.showUntrackedFilesconfiguration.Problem
Users managing dotfiles with a bare git repository (a common pattern) set
status.showUntrackedFiles=noin their repo's git config to avoid showing every file in the home directory as untracked. VS Code'sgit.untrackedChangessetting doesn't respect this git configuration, forcing users to manually set it tohidden— which then applies to all repositories.Solution
Add a 4th enum value
"default"to thegit.untrackedChangessetting. When selected:status.showUntrackedFilesfrom the repository's effective git configno→ behaves like"hidden"(uses-unoflag)"mixed"(uses-uallflag)The resolution happens at the start of
getStatus(), so all downstream logic (resource grouping, count badge, unstaging) works transparently.Files changed
package.json"default"to enum + enumDescriptionspackage.nls.jsonrepository.ts"default"viagit config, update type annotations