Skip to content

perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat - #4843

Merged
juliusmarminge merged 7 commits into
pingdotgg:mainfrom
UtkarshUsername:fix/git-status-numstat-merge
Jul 29, 2026
Merged

perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat#4843
juliusmarminge merged 7 commits into
pingdotgg:mainfrom
UtkarshUsername:fix/git-status-numstat-merge

Conversation

@UtkarshUsername

@UtkarshUsername UtkarshUsername commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

What Changed

Merged two separate git diff --numstat and git diff --cached --numstat calls into a single git diff HEAD --numstat call. Also simplified the parsing loop from merging staged+unstaged entries into a single flat iteration.

Why

The separate staged/unstaged breakdown was never used individually. Both were immediately summed together per file path into a combined total. git diff HEAD --numstat produces the same combined total directly, eliminating one git subprocess per status refresh.

Benchmark (20 runs each):

  • Old (2 calls): ~790ms
  • New (1 call): ~311ms
  • Saving: ~479ms per refresh

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Medium Risk
Behavior change to how line stats are computed for statusDetails (net vs HEAD, not summed staged+unstaged); low blast radius but UI/commit flows that show those numbers may differ for mixed-index files.

Overview
readStatusDetailsLocal in GitVcsDriverCore now loads working-tree line stats with a single git diff HEAD --numstat instead of parallel git diff --numstat and git diff --cached --numstat, cutting one Git subprocess per status refresh.

Per-file insertions/deletions are taken directly from that output (net vs HEAD), which fixes double-counting when the same path has both staged and unstaged edits; parsing no longer merges two numstat maps by summing.

When git diff HEAD fails on a repo with no commits (unborn HEAD), the driver detects that stderr via isUnbornHeadStderr and falls back to the previous two-diff merge; other numstat failures surface as GitCommandError.

Integration tests cover combined staged/unstaged edits on one file and staged counts on unborn HEAD.

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

Note

Merge separate staged/unstaged git diff --numstat calls into a single git diff HEAD --numstat in statusDetails

  • Replaces two separate git diff --numstat (unstaged) and git diff --cached --numstat (staged) calls with a single git diff HEAD --numstat, so per-file insertion/deletion counts reflect combined staged and unstaged changes relative to HEAD.
  • Adds fallback handling for unborn HEAD: when git diff HEAD --numstat exits non-zero with an unborn-HEAD stderr, both git diff --numstat and git diff --cached --numstat are run and their results merged per file.
  • Non-unborn-HEAD failures now propagate as a GitCommandError instead of being silently ignored.
  • Behavioral Change: file stats now represent combined diff from HEAD rather than independent staged and unstaged counts, which changes reported insertions/deletions for files modified in both index and working tree.

Macroscope summarized 2b56da6.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 55ef3b7b-4efc-45ea-943f-1614e73cd060

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:S 10-29 changed lines (additions + deletions). labels Jul 29, 2026
@UtkarshUsername UtkarshUsername changed the title fix(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat Jul 29, 2026

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Effect service conventions review: one finding — a backend behavior change in GitVcsDriverCore.statusDetails lands without focused test coverage.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
Comment on lines +1514 to +1516
const [numstatStdout, defaultRefResult, hasPrimaryRemote] = yield* Effect.all(
[
runGitStdout("GitVcsDriver.statusDetails.numstat", cwd, ["diff", "HEAD", "--numstat"]),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes statusDetails backend behavior (staged+unstaged line counts are now a single diff HEAD instead of summed diff + diff --cached), so it should come with focused tests in GitVcsDriverCore.test.ts rather than none. Two cases worth covering:

  • a file that is staged and then modified again in the working tree, asserting the counts are no longer double-counted;
  • a repository with no commits yet (unborn HEAD): git diff HEAD --numstat exits non-zero there, and because runGitStdout is called without allowNonZeroExit, statusDetails would now fail where the previous diff / diff --cached pair succeeded. If that case is reachable, handle it (e.g. allowNonZeroExit plus an empty-stat fallback, or diff against the empty tree) and pin it with a test.

Posted via Macroscope — Effect Service Conventions

@macroscopeapp

macroscopeapp Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved 2b56da6

Performance optimization that merges two git diff calls into one, with appropriate fallback handling for edge cases (unborn HEAD) and new test coverage addressing both scenarios raised in review feedback.

You can customize Macroscope's approvability policy. Learn more.

Comment thread apps/server/src/vcs/GitVcsDriverCore.ts
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
@github-actions github-actions Bot added size:M 30-99 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Jul 29, 2026
@UtkarshUsername
UtkarshUsername marked this pull request as draft July 29, 2026 15:03

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up on the numstat consolidation: the new unborn-HEAD fallback now hides genuine git diff failures, and the changed counting behavior is still untested.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
@UtkarshUsername
UtkarshUsername force-pushed the fix/git-status-numstat-merge branch from b3650f8 to 41277f6 Compare July 29, 2026 15:28
@UtkarshUsername
UtkarshUsername marked this pull request as ready for review July 29, 2026 15:42
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Jul 29, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 66de31a. Configure here.

Comment thread apps/server/src/vcs/GitVcsDriverCore.ts
@macroscopeapp
macroscopeapp Bot dismissed their stale review July 29, 2026 15:59

Dismissing prior approval to re-evaluate 812b47c

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One residual finding on the new unborn-HEAD fallback in readStatusDetailsLocal. The classification via isUnbornHeadStderr addresses the earlier concern; the remaining issue is the suppressed failure channel in the fallback commands.

Posted via Macroscope — Effect Service Conventions

Comment thread apps/server/src/vcs/GitVcsDriverCore.ts Outdated
Both git diff --numstat and git diff --cached --numstat exit 0 on an
unborn HEAD (empty output), so the allowNonZeroExit relaxation is
unnecessary. Dropping it lets genuine failures propagate as typed
GitCommandError instead of silently reporting zero changes.
@juliusmarminge
juliusmarminge merged commit faea70a into pingdotgg:main Jul 29, 2026
17 checks passed
ohbentos pushed a commit to ohbentos/t3code that referenced this pull request Jul 29, 2026
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Jul 29, 2026
## What's Changed
* fix(server): detect repositories after initialization by @StiensWout in pingdotgg/t3code#4848
* perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat by @UtkarshUsername in pingdotgg/t3code#4843
* fix(git): disable external diff for review diff previews by @ohbentos in pingdotgg/t3code#4854
* Fix editable file focus and live syntax highlighting by @jakeleventhal in pingdotgg/t3code#3979
* fix(web): remember the rendered-markdown choice across threads by @Sy-D in pingdotgg/t3code#4853

## New Contributors
* @ohbentos made their first contribution in pingdotgg/t3code#4854
* @Sy-D made their first contribution in pingdotgg/t3code#4853

**Full Changelog**: pingdotgg/t3code@v0.0.31-nightly.20260729.946...v0.0.31-nightly.20260729.948

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.31-nightly.20260729.948
github-actions Bot added a commit to omarcresp/t3code-flake that referenced this pull request Jul 29, 2026
## What's Changed
* Fix Connect sign-in settings label by @juliusmarminge in pingdotgg/t3code#4806
* fix(desktop): restore T3 Connect sign-in by @PixPMusic in pingdotgg/t3code#4809
* Simplify files panel header by @juliusmarminge in pingdotgg/t3code#4828
* build(desktop): reduce installed app size by ~300MB by @wukko in pingdotgg/t3code#4824
* Update model version from claude-opus-4-8 to claude-opus-5 by @juliusmarminge in pingdotgg/t3code#4832
* Preserve the thread shell while detail loads by @juliusmarminge in pingdotgg/t3code#4830
* Reduce idle work and disk churn with native resource diagnostics by @juliusmarminge in pingdotgg/t3code#2679
* fix(server): detect repositories after initialization by @StiensWout in pingdotgg/t3code#4848
* perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat by @UtkarshUsername in pingdotgg/t3code#4843
* fix(git): disable external diff for review diff previews by @ohbentos in pingdotgg/t3code#4854
* Fix editable file focus and live syntax highlighting by @jakeleventhal in pingdotgg/t3code#3979
* fix(web): remember the rendered-markdown choice across threads by @Sy-D in pingdotgg/t3code#4853

## New Contributors
* @wukko made their first contribution in pingdotgg/t3code#4824
* @ohbentos made their first contribution in pingdotgg/t3code#4854
* @Sy-D made their first contribution in pingdotgg/t3code#4853

**Full Changelog**: pingdotgg/t3code@v0.0.30...v0.0.31

## What's Changed
* Fix Connect sign-in settings label by @juliusmarminge in pingdotgg/t3code#4806
* fix(desktop): restore T3 Connect sign-in by @PixPMusic in pingdotgg/t3code#4809
* Simplify files panel header by @juliusmarminge in pingdotgg/t3code#4828
* build(desktop): reduce installed app size by ~300MB by @wukko in pingdotgg/t3code#4824
* Update model version from claude-opus-4-8 to claude-opus-5 by @juliusmarminge in pingdotgg/t3code#4832
* Preserve the thread shell while detail loads by @juliusmarminge in pingdotgg/t3code#4830
* Reduce idle work and disk churn with native resource diagnostics by @juliusmarminge in pingdotgg/t3code#2679
* fix(server): detect repositories after initialization by @StiensWout in pingdotgg/t3code#4848
* perf(server): merge separate staged/unstaged numstat calls into single diff HEAD --numstat by @UtkarshUsername in pingdotgg/t3code#4843
* fix(git): disable external diff for review diff previews by @ohbentos in pingdotgg/t3code#4854
* Fix editable file focus and live syntax highlighting by @jakeleventhal in pingdotgg/t3code#3979
* fix(web): remember the rendered-markdown choice across threads by @Sy-D in pingdotgg/t3code#4853

## New Contributors
* @wukko made their first contribution in pingdotgg/t3code#4824
* @ohbentos made their first contribution in pingdotgg/t3code#4854
* @Sy-D made their first contribution in pingdotgg/t3code#4853

**Full Changelog**: pingdotgg/t3code@v0.0.30...v0.0.31

Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants