Skip to content

fix(git): skip untracked scan when HK_STASH_UNTRACKED=false#861

Merged
jdx merged 1 commit intomainfrom
fix/git-status-skip-untracked-when-disabled
Apr 23, 2026
Merged

fix(git): skip untracked scan when HK_STASH_UNTRACKED=false#861
jdx merged 1 commit intomainfrom
fix/git-status-skip-untracked-when-disabled

Conversation

@jdx
Copy link
Copy Markdown
Owner

@jdx jdx commented Apr 23, 2026

Summary

  • When GIT_WORK_TREE points at a large directory (e.g. a YADM dotfile repo where the worktree is $HOME), the unconditional git status --untracked-files=all scan takes tens of seconds and emits hundreds of megabytes of output on every hk invocation.
  • HK_STASH_UNTRACKED=false previously had no effect on the status scan — it only suppressed stashing. This change honors it in Git::status() (and the internal stash porcelain parse, which already ignores untracked entries) so users of large worktrees can opt out of the scan entirely. Both the libgit2 and shell-git paths are updated.
  • Fixes #860.

Test plan

  • mise run test:bats test/bare_repo_env_vars.bats (7 tests × 2 modes)
  • mise run test:bats test/stash_untracked_with_partial_stash.bats, test/stash_preservation_on_error.bats, test/pre_commit_does_not_stash_staged_only_files.bats, test/git_status_ad_deleted.bats, test/cargo_fmt_does_not_stage_manifest.bats
  • mise run test:cargo (145 passed)
  • New regression test: HK_STASH_UNTRACKED=false skips untracked scan in large worktree (#860)

🤖 Generated with Claude Code


Note

Medium Risk
Changes how Git::status() (libgit2 and shell-git paths) and stash detection call git status, which can affect which files hk considers (especially untracked files) and therefore which steps run. The behavior is gated behind HK_STASH_UNTRACKED=false, but it touches core git/file-detection logic.

Overview
Honors HK_STASH_UNTRACKED=false by skipping untracked-file enumeration during status collection (using --untracked-files=no for shell git and disabling untracked options for libgit2) to avoid expensive scans when GIT_WORK_TREE is very large.

Updates the stash porcelain parse to likewise avoid untracked scanning when untracked stashing is disabled, documents the new behavior in docs/environment_variables.md, and adds a Bats regression test ensuring untracked “junk” in a large worktree doesn’t appear in hk check --all output.

Reviewed by Cursor Bugbot for commit 4049f37. Bugbot is set up for automated code reviews on this repo. Configure here.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 23, 2026

Greptile Summary

This PR makes HK_STASH_UNTRACKED=false actually suppress the underlying git status --untracked-files=all scan, fixing a serious performance regression for large GIT_WORK_TREE directories (e.g. YADM dotfile repos where the worktree is $HOME). Both the libgit2 path (StatusOptions::include_untracked / recurse_untracked_dirs) and the shell-git path (the --untracked-files=… flag) are updated in Git::status(), and the stash porcelain parse in section 3 is updated for consistency. Documentation is updated to document the new side-effect of the flag.

Confidence Score: 5/5

Safe to merge — the logic change is correct in both code paths, preserves existing behaviour when the env var is not set, and is documented.

The only open concern (regression-test assertion quality) was already raised in a prior review thread; no new P0/P1 issues are present. The Rust change is minimal, well-contained, and correctly honours the existing HK_STASH_UNTRACKED semantics in all four affected code sites.

No files require special attention beyond the already-discussed test assertion in test/bare_repo_env_vars.bats.

Important Files Changed

Filename Overview
src/git.rs Reads HK_STASH_UNTRACKED once per status() call and threads it through both the libgit2 and shell-git code paths; also propagates it to the stash porcelain parse in section 3 — logic is correct and complete.
docs/environment_variables.md Adds a clear explanation of the new HK_STASH_UNTRACKED=false scan-skipping behavior, including the YADM / large-GIT_WORK_TREE motivation — accurate and useful.
test/bare_repo_env_vars.bats Regression test for #860 exercises the code path correctly but the refute_output assertion (already flagged in a prior review thread) may pass even without the fix since untracked filenames are not normally included in hk check --all output.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["Git::status() called"] --> B["read *env::HK_STASH_UNTRACKED\n→ include_untracked: bool"]
    B --> C{libgit2 repo\navailable?}
    C -- yes --> D["status_options.include_untracked(include_untracked)\nstatus_options.recurse_untracked_dirs(include_untracked)"]
    D --> E["run libgit2 staged scan\nrun libgit2 workdir scan\n(untracked entries absent when false)"]
    C -- no --> F{include_untracked?}
    F -- true --> G["--untracked-files=all"]
    F -- false --> H["--untracked-files=no"]
    G & H --> I["git status --porcelain FLAG -z"]
    E & I --> J["return GitStatus\n(untracked_files empty when false)"]
    J --> K["stash porcelain parse (§3)\nsame FLAG applied"]
Loading

Reviews (2): Last reviewed commit: "fix(git): skip untracked scan when HK_ST..." | Re-trigger Greptile

Comment thread test/bare_repo_env_vars.bats
When `GIT_WORK_TREE` points at a very large directory (e.g. a YADM
dotfile repo where the worktree is `$HOME`), the unconditional
`git status --untracked-files=all` scan takes tens of seconds and
produces hundreds of megabytes of output on every hk invocation.

The `HK_STASH_UNTRACKED=false` env var previously had no effect on the
status scan itself — it only suppressed stashing. Honor it in
`Git::status()` (and the internal stash porcelain parse, which already
ignores untracked entries) so that users of large worktrees can opt out
of the scan entirely. Both the libgit2 and shell-git paths are updated.

Closes #860

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@jdx jdx force-pushed the fix/git-status-skip-untracked-when-disabled branch from 5fe8fdf to 4049f37 Compare April 23, 2026 20:48
@jdx jdx enabled auto-merge (squash) April 23, 2026 20:56
@jdx jdx merged commit dcc9e64 into main Apr 23, 2026
20 checks passed
@jdx jdx deleted the fix/git-status-skip-untracked-when-disabled branch April 23, 2026 20:58
@jdx jdx mentioned this pull request Apr 23, 2026
jdx added a commit that referenced this pull request Apr 24, 2026
### 🐛 Bug Fixes

- **(git)** skip untracked scan when HK_STASH_UNTRACKED=false by
[@jdx](https://github.com/jdx) in
[#861](#861)
- **(run)** add post-commit and pre-rebase subcommands by
[@jdx](https://github.com/jdx) in
[#858](#858)

### 📚 Documentation

- **(install)** recommend global hooks as primary setup path by
[@jdx](https://github.com/jdx) in
[#855](#855)
- add cross-site announcement banner by [@jdx](https://github.com/jdx)
in [#857](#857)
- respect banner expires field by [@jdx](https://github.com/jdx) in
[#862](#862)

### 🔍 Other Changes

- vendor bats test helpers instead of git submodules by
[@jdx](https://github.com/jdx) in
[#859](#859)

### 📦️ Dependency Updates

- bump communique to 1.0.3 by [@jdx](https://github.com/jdx) in
[#863](#863)
- update anthropics/claude-code-action digest to e58dfa5 by
[@renovate[bot]](https://github.com/renovate[bot]) in
[#864](#864)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk release bookkeeping only: version numbers, generated
CLI/docs, and lockfile dependency bumps with no runtime logic changes.
> 
> **Overview**
> **Release prep for `v1.44.1`.** Updates `Cargo.toml`/`Cargo.lock`
(including `libc`) and all version references in generated CLI docs
(`docs/cli/*`, `hk.usage.kdl`).
> 
> Refreshes documentation examples to reference the new `v1.44.1` Pkl
package URLs and adds the `1.44.1` entry to `CHANGELOG.md`.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
d7637d4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: mise-en-dev <[email protected]>
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