Skip to content

perf(git): optimize git status for large monorepos#1613

Merged
arnestrickmann merged 2 commits intogeneralaction:mainfrom
kchung:chung/optimize-git-status
Mar 29, 2026
Merged

perf(git): optimize git status for large monorepos#1613
arnestrickmann merged 2 commits intogeneralaction:mainfrom
kchung:chung/optimize-git-status

Conversation

@kchung
Copy link
Copy Markdown
Contributor

@kchung kchung commented Mar 27, 2026

Summary

Optimizes GitService.getStatus() for large monorepos by running git commands in parallel and adding flags to reduce unnecessary work:

  • Parallel execution: git status and both git diff --numstat commands now run concurrently via Promise.all instead of sequentially
  • --no-optional-locks: Prevents git status from blocking when a concurrent git fetch holds the index lock
  • --no-ahead-behind: Skips commit-graph traversal for branch tracking info we don't use
  • --untracked-files=normal: Shows untracked directories as single entries instead of recursively enumerating every file within them

Fixes

N/A

Snapshot

Testing steps in the video:

  1. Use a super large monorepo
  2. Refresh the Electron App (cmd + r)
  3. Click on a task
  4. Open the sidebar to see the changes

This test uses the exact same repo with the exact same changes, one running the latest Emdash dist and one running this PR. This is running on an Apple M4 Max 64GB

Before

before.mov

After

after.mov

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • Chore (refactoring code, technical debt, workflow improvements)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (does not change functionality, e.g. code style improvements, linting)
  • This change requires a documentation update

Mandatory Tasks

  • I have self-reviewed the code
  • A decent size PR without self-review might be rejected

Checklist

  • I have read the contributing guide
  • My code follows the style guidelines of this project (pnpm run format)
  • I have commented my code, particularly in hard-to-understand areas
  • I have checked if my PR needs changes to the documentation
  • I have checked if my changes generate no new warnings (pnpm run lint)
  • I have added tests that prove my fix is effective or that my feature works
  • I haven't checked if new and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • Performance Improvements

    • Status and file-change detection now run concurrently for faster, more responsive results.
  • Compatibility

    • Improved fallback handling for older Git versions to ensure status reporting works across environments.
  • Reliability

    • More consistent status information, safer Git options to reduce interference, and non-blocking handling of auxiliary diff checks to avoid disrupting results.

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 27, 2026

@kchung is attempting to deploy a commit to the General Action Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f21619d8-ab0b-4e98-9c66-492fb0cc2bfb

📥 Commits

Reviewing files that changed from the base of the PR and between 98076ea and c18ded4.

📒 Files selected for processing (1)
  • src/main/services/GitService.ts

📝 Walkthrough

Walkthrough

Refactors GitService.getStatus to run git status (porcelain v2 with fallback) concurrently with staged and unstaged git diff --numstat, adds --no-optional-locks and --no-ahead-behind, short-circuits on empty status output, and builds staged/unstaged maps from diff outputs.

Changes

Cohort / File(s) Summary
Git Status Parallelization
src/main/services/GitService.ts
Refactored getStatus() to run git status (porcelain v2, fallback) and two git diff --numstat commands (staged & unstaged) concurrently via Promise.all. Added --no-optional-locks to commands, --no-ahead-behind to status, changed untracked handling, short-circuits when statusOutput.trim() is empty, and parses status into entries then maps from diff outputs.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant GitService
  participant GitCLI

  Client->>GitService: getStatus(taskPath)
  GitService->>GitCLI: git status --porcelain=v2 -z --no-ahead-behind --no-optional-locks
  GitService->>GitCLI: git diff --numstat --cached --no-optional-locks
  GitService->>GitCLI: git diff --numstat --no-optional-locks
  Note right of GitCLI: Commands run concurrently
  GitCLI-->>GitService: statusOutput, stagedNumstat, unstagedNumstat
  GitService->>GitService: if statusOutput.trim() === '' -> return []
  GitService->>GitService: parse statusOutput -> entries
  GitService->>GitService: build staged/unstaged maps from numstat
  GitService-->>Client: entries (with staged/unstaged info)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 Three commands race beneath moonlight,
Porcelain whispers, diffs in flight,
Locks laid down, outputs combined,
Maps and entries neatly aligned,
A rabbit hops—concurrency delight ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'perf(git): optimize git status for large monorepos' directly and accurately summarizes the main change—optimizing the GitService.getStatus() function for large monorepos through parallelization and git flags.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@kchung kchung marked this pull request as ready for review March 27, 2026 22:43
Copy link
Copy Markdown
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Run status and numstat commands in parallel instead of sequentially.
Add --no-optional-locks to avoid blocking on concurrent git processes,
--no-ahead-behind to skip commit-graph walks, and --untracked-files=normal
to avoid recursive enumeration of untracked directories.
@kchung kchung force-pushed the chung/optimize-git-status branch from b2f6a58 to 98076ea Compare March 27, 2026 22:45
@arnestrickmann
Copy link
Copy Markdown
Contributor

@kchung
Thank you for taking this on! (I texted you on LinkedIn btw)

proper review soon!

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/services/GitService.ts`:
- Around line 171-183: The git status flag `--untracked-files=normal` returns
directory entries which breaks file-only logic in functions like
countFileNewlinesCapped and deleteUntracked; update both execFileAsync calls
that pass '--untracked-files=normal' (the two occurrences shown near the
execFileAsync invocations using MAX_DIFF_OUTPUT_BYTES) to use
'--untracked-files=all' instead so untracked directories are expanded into
individual file paths that the rest of GitService.ts can handle; ensure both
fallback and primary git calls are changed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3bc84f9d-fede-4124-bfec-f72de417f856

📥 Commits

Reviewing files that changed from the base of the PR and between d197ba5 and b2f6a58.

📒 Files selected for processing (1)
  • src/main/services/GitService.ts

Ensures individual file paths are returned instead of directory
entries, which downstream file-level operations depend on.
@kchung
Copy link
Copy Markdown
Contributor Author

kchung commented Mar 27, 2026

Thanks @arnestrickmann! I'll connect with you in a bit!

@arnestrickmann
Copy link
Copy Markdown
Contributor

Cool!

Looking forward to connect and also jam on Emdash improvements / wishes you might have for future releases. @kchung

@arnestrickmann
Copy link
Copy Markdown
Contributor

Thanks again, for the contribution! @kchung

@arnestrickmann arnestrickmann merged commit 7d32559 into generalaction:main Mar 29, 2026
3 of 4 checks passed
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.

2 participants