Skip to content

Comments

perf: skip stash operations when no unstaged changes#457

Merged
jdx merged 2 commits intomainfrom
skip-stash-when-no-unstaged
Nov 21, 2025
Merged

perf: skip stash operations when no unstaged changes#457
jdx merged 2 commits intomainfrom
skip-stash-when-no-unstaged

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Nov 21, 2025

Summary

Optimizes the stash workflow to skip unnecessary git operations when running hooks with only staged changes (no unstaged or untracked files).

Problem

Previously, stash_unstaged() would run 3 git commands even when there were no unstaged files to stash:

  • git diff --name-only: ~40ms
  • git ls-files -m: ~460ms
  • git status --porcelain: ~740ms

Total wasted time: ~1.2 seconds per hook run in staged-only workflows.

Solution

Added an early check in hook.rs that inspects git_status.unstaged_files and git_status.untracked_files before invoking the stash logic. When there are no unstaged changes, the stash is skipped entirely with a user-visible message.

Performance Impact

  • Staged-only workflow: Saves ~1.2 seconds per hook run
  • Mixed changes (staged + unstaged): No change, stash still runs correctly

Testing

Verified with two scenarios:

  1. Staged only: Hook runtime improved from ~8.2s to ~7.0s, stash skipped
  2. Mixed staged/unstaged: Hook runtime unchanged (~16.7s), stash runs correctly

The fix is particularly beneficial for common workflows where developers stage changes and commit without unstaged files in the working tree.


Note

Skips stash work when there are no unstaged/untracked changes, updating progress and preserving existing stash flow otherwise.

  • Hook runner (src/hook.rs):
    • Gate stash operations behind has_unstaged_changes using git_status.unstaged_files and HK_STASH_UNTRACKED with git_status.untracked_files.
    • If none, update file_progress (message: "No unstaged changes to stash") and mark ProgressStatus::Done.
    • Otherwise, keep existing flow: capture_index(files) then stash_unstaged(...).

Written by Cursor Bugbot for commit 631a473. This will update automatically on new commits. Configure here.

jdx added 2 commits November 21, 2025 16:04
When running hooks with only staged changes (no unstaged or untracked files),
skip the stash logic entirely to avoid unnecessary git operations.

Previously, stash_unstaged() would run 3 git commands even when there were
no unstaged files to detect:
- git diff --name-only: ~40ms
- git ls-files -m: ~460ms
- git status --porcelain: ~740ms

This adds an early check using git_status.unstaged_files and
git_status.untracked_files to skip stash when not needed.

Performance improvement:
- Staged-only workflow: saves ~1.2 seconds
- Mixed changes: no change, stash still runs correctly
@jdx jdx enabled auto-merge (squash) November 21, 2025 22:12
@jdx jdx merged commit cbed6e3 into main Nov 21, 2025
14 checks passed
@jdx jdx deleted the skip-stash-when-no-unstaged branch November 21, 2025 22:12
@jdx jdx mentioned this pull request Nov 21, 2025
jdx added a commit that referenced this pull request Nov 21, 2025
## [1.24.0](https://github.com/jdx/hk/compare/v1.23.0..v1.24.0) -
2025-11-21

### 🚀 Features

- hook stage by [@thejcannon](https://github.com/thejcannon) in
[#448](#448)

### 🐛 Bug Fixes

- Pass/render `stdin` for `hk test` tests by
[@thejcannon](https://github.com/thejcannon) in
[#455](#455)

### 📚 Documentation

- Fix `from_ref` docstring by
[@thejcannon](https://github.com/thejcannon) in
[#454](#454)

### ⚡ Performance

- skip stash operations when no unstaged changes by
[@jdx](https://github.com/jdx) in
[#457](#457)
- skip staging when jobs are skipped by conditions by
[@jdx](https://github.com/jdx) in
[#458](#458)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Bump to 1.24.0 with widespread docs/templates updates, corrected CLI
help text, and a small dependency update.
> 
> - **Version bump and release notes**
> - Update crate/app version to `1.24.0` in `Cargo.toml`, `Cargo.lock`,
`hk.usage.kdl`, `docs/cli/commands.json` and docs.
>   - Add `1.24.0` entry to `CHANGELOG.md`.
> - **Docs and templates**
> - Replace package URLs and examples from `v1.23.0` to `v1.24.0` across
docs and example `*.pkl` files.
>   - Update `src/cli/init.rs` template to reference `v1.24.0`.
>   - Adjust version display in CLI docs (`docs/cli/index.md`).
> - **CLI help text fixes**
> - Clarify `--from-ref` help and simplify `--no-fail-fast` descriptions
in `docs/cli/*`, `docs/cli/commands.json`, and `hk.usage.kdl`.
> - **Config error message**
> - Update example `amends` URI in `src/config.rs` error guidance to
`v1.24.0`.
> - **Dependencies**
>   - Bump `pest`/`pest_*` crates to `2.8.4` in `Cargo.lock`.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
44258ad. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: mise-en-dev <[email protected]>
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Nov 27, 2025
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [hk](https://github.com/jdx/hk) | minor | `1.22.0` -> `1.25.0` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jdx/hk (hk)</summary>

### [`v1.25.0`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1250---2025-11-25)

[Compare Source](jdx/hk@v1.24.1...v1.25.0)

##### 🚀 Features

- add fix\_smart\_quotes builtin by [@&#8203;joonas](https://github.com/joonas) in [#&#8203;463](jdx/hk#463)

##### 🐛 Bug Fixes

- Use `stage = "<JOB_FILES>"` for the builtins by [@&#8203;thejcannon](https://github.com/thejcannon) in [#&#8203;465](jdx/hk#465)
- Actually makes `files` for step tests default to write keys by [@&#8203;thejcannon](https://github.com/thejcannon) in [#&#8203;464](jdx/hk#464)
- remove test cleanup to prevent race conditions by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;468](jdx/hk#468)

### [`v1.24.1`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1241---2025-11-22)

[Compare Source](jdx/hk@v1.24.0...v1.24.1)

##### ⚡ Performance

- show progress bars before expensive git status call by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;459](jdx/hk#459)

### [`v1.24.0`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1240---2025-11-21)

[Compare Source](jdx/hk@v1.23.0...v1.24.0)

##### 🚀 Features

- hook stage by [@&#8203;thejcannon](https://github.com/thejcannon) in [#&#8203;448](jdx/hk#448)

##### 🐛 Bug Fixes

- Pass/render `stdin` for `hk test` tests by [@&#8203;thejcannon](https://github.com/thejcannon) in [#&#8203;455](jdx/hk#455)

##### 📚 Documentation

- Fix `from_ref` docstring by [@&#8203;thejcannon](https://github.com/thejcannon) in [#&#8203;454](jdx/hk#454)

##### ⚡ Performance

- skip stash operations when no unstaged changes by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;457](jdx/hk#457)
- skip staging when jobs are skipped by conditions by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;458](jdx/hk#458)

### [`v1.23.0`](https://github.com/jdx/hk/blob/HEAD/CHANGELOG.md#1230---2025-11-21)

[Compare Source](jdx/hk@v1.22.0...v1.23.0)

##### 🚀 Features

- **(vacuum)** new builtin by [@&#8203;scop](https://github.com/scop) in [#&#8203;414](jdx/hk#414)
- add --stats flag to show file counts per step by [@&#8203;jdx](https://github.com/jdx) in [#&#8203;446](jdx/hk#446)
- Plumb `stage` through CLI and PKL by [@&#8203;thejcannon](https://github.com/thejcannon) in [#&#8203;442](jdx/hk#442)

##### 🐛 Bug Fixes

- **(cli)** check help description by [@&#8203;scop](https://github.com/scop) in [#&#8203;439](jdx/hk#439)

##### 📚 Documentation

- **(stash)** rephrase uncommitted -> unstaged by [@&#8203;scop](https://github.com/scop) in [#&#8203;451](jdx/hk#451)
- re-Remove "auto" stash value by [@&#8203;thejcannon](https://github.com/thejcannon) in [#&#8203;444](jdx/hk#444)
- Delete `schema.md` by [@&#8203;thejcannon](https://github.com/thejcannon) in [#&#8203;445](jdx/hk#445)
- fix --fix description by [@&#8203;scop](https://github.com/scop) in [#&#8203;450](jdx/hk#450)

##### 📦️ Dependency Updates

- update actions/checkout digest to [`93cb6ef`](jdx/hk@93cb6ef) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;452](jdx/hk#452)
- update anthropics/claude-code-action digest to [`6902c22`](jdx/hk@6902c22) by [@&#8203;renovate\[bot\]](https://github.com/renovate\[bot]) in [#&#8203;453](jdx/hk#453)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi4xOS4wIiwidXBkYXRlZEluVmVyIjoiNDIuMTkuNyIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsiUmVub3ZhdGUgQm90Il19-->
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