Repository navigation
Description
gh stack rebase feels noticeably slower than manually rebasing each branch onto its predecessor in a large monorepo I work on. Working-tree cleanliness checks appear to account for part of the extra time, even when there are no changes to report.
Observed behavior
The cleanliness check runs git status --porcelain --untracked-files=all:
gh-stack/internal/git/gitops.go
Lines 846 to 852 in bd0a325
| func (d *defaultOps) HasUncommittedChanges() (bool, error) { | |
| out, err := d.run("status", "--porcelain", "--untracked-files=all") | |
| if err != nil { | |
| return false, err | |
| } | |
| return out != "", nil | |
| } |
In my checkout, this command consistently takes about 2.8 seconds. Rebase checks cleanliness during preflight and again when preparing branches, so the cost accumulates across a stack.
Measurements
I ran each of these commands three times in the same checkout, with short pauses between runs:
time git status --porcelain --untracked-files=all
time git status --porcelain --untracked-files=normal| Untracked mode | Run 1 | Run 2 | Run 3 | Mean |
|---|---|---|---|---|
all |
2.848 s | 2.610 s | 3.014 s | 2.824 s |
normal |
0.236 s | 0.243 s | 0.240 s | 0.240 s |
The roughly 11.8× difference suggests that exhaustive untracked-file scanning contributes substantially to the cost of each check. These are timings of the status command, not an end-to-end rebase benchmark; I have not measured how much of the total rebase time is spent in these checks.
Expected behavior
Rebasing a stack in a large repository should avoid substantial repeated filesystem-scanning overhead while retaining the existing checks that protect local work.
Related: #579 reduced redundant Git and worktree lookups, but individual cleanliness checks can still be expensive.
Related draft PR
I have a candidate fix in allanlewis#1. It is hosted in my fork because I do not have permission to open an upstream PR in github/gh-stack. It targets my fork’s main, which matches upstream main.
AI assistance: Codex helped investigate the implementation, prepare and test the candidate fix, and draft this report. The timings above were measured by me.
Activity
[-]Reduce rebase overhead by avoiding exhaustive untracked-file enumeration[/-][+]Slow rebase in large monorepos: repeated cleanliness checks take several seconds[/+][-]Slow rebase in large monorepos: repeated cleanliness checks take several seconds[/-][+]`gh stack rebase` is slow in large monorepos[/+][-]`gh stack rebase` is slow in large monorepos[/-][+]Rebasing a stack unnecessarily enumerates each untracked file[/+]