Merged
Conversation
…nged - Reduce RAGE_RESTART_THRESHOLD_MS from 120s to 90s. - Store the current git branch in dev-state.json on shutdown. On startup, if the stored branch and current branch are both known but differ, don't flag the restart as a rage restart — the user switched branches. - Add a test case that verifies branch changes suppress the rage-restart flag. Co-Authored-By: Claude <noreply@anthropic.com>
Move the inline getGitBranch() from next-dev.ts into packages/next/src/lib/helpers/get-git-branch.ts and import it from both next-dev.ts and trace-uploader.ts (which had its own open-coded version). Co-Authored-By: Claude <noreply@anthropic.com>
Replace the single-function get-git-branch.ts with a general git.ts module. Add getGitCommit() alongside getGitBranch() and use it in trace-uploader.ts to replace its remaining open-coded spawnSync call, removing the child_process import from that file entirely. Co-Authored-By: Claude <noreply@anthropic.com>
Callers no longer need to know about these env vars; the preference logic lives alongside the git queries that it overrides. Co-Authored-By: Claude <noreply@anthropic.com>
Contributor
Tests Passed |
Contributor
Stats from current PR✅ No significant changes detected📊 All Metrics📖 Metrics GlossaryDev Server Metrics:
Build Metrics:
Change Thresholds:
⚡ Dev Server
📦 Dev Server (Webpack) (Legacy)📦 Dev Server (Webpack)
⚡ Production Builds
📦 Production Builds (Webpack) (Legacy)📦 Production Builds (Webpack)
📦 Bundle SizesBundle Sizes⚡ TurbopackClient Main Bundles
Server Middleware
Build DetailsBuild Manifests
📦 WebpackClient Main Bundles
Polyfills
Pages
Server Edge SSR
Middleware
Build DetailsBuild Manifests
Build Cache
🔄 Shared (bundler-independent)Runtimes
📎 Tarball URL |
git rev-parse --abbrev-ref HEAD outputs "HEAD" (exit 0) on a fresh repo with no commits, which the helper converted to an empty string. This made the branch-change check always fall back to time-only detection in test fixtures that initialise a bare git repo. Switch to git symbolic-ref --short HEAD, which returns the branch name correctly on empty repos and exits non-zero in detached HEAD state (caught and returned as ""). Co-Authored-By: Claude <noreply@anthropic.com>
wbinnssmith
commented
Apr 9, 2026
Extract a named DevStateEntry type in next-dev.ts to replace the two separate inline type casts for reading and writing the dev-state file. This avoids duplicating the shape and makes it clear all fields are optional for backward compatibility with older state entries. Also update the next-server-nft inline snapshot to include git.js, which now appears in the standalone trace because trace-uploader.ts imports from the new helpers/git module. Co-Authored-By: Claude <noreply@anthropic.com>
wbinnssmith
commented
Apr 9, 2026
getGitBranch and getGitCommit now return string | undefined on failure rather than ''. Empty string was semantically ambiguous; undefined makes the "unknown" case explicit and lets callers use ?? / optional chaining naturally. Update TraceMetadata.branch/commit to optional accordingly. Co-Authored-By: Claude <noreply@anthropic.com>
The API server expects branch and commit to always be string fields. After getGitBranch/getGitCommit were changed to return string | undefined, JSON.stringify would silently drop undefined values, changing the wire format. Normalize at the call site with ?? '' so the payload stays backward compatible while keeping the cleaner internal return type. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
lukesandberg
approved these changes
Apr 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
Two behaviour changes to the rage-restart detection in
next dev, plus a refactor of the git helper code:Lower the rage-restart threshold from 120s to 90s. The previous window was too generous; 90 s is a better match for the workflow of stopping and immediately restarting the dev server.
Don't count a restart as a rage-restart if the git branch changed. A common workflow is: stop the dev server,
git checkout <other-branch>, restart. That sequence has nothing to do with frustration — it's intentional. The dev state file now records the current git branch on shutdown, and on startup the recorded branch is compared to the current one. If they differ the restart is not flagged. If either branch is unknown (detached HEAD, not a git repo, etc.) the comparison is skipped and we fall back to time-only detection, preserving the existing behaviour.Why?
The rage-restart signal is meant to detect genuine frustration with the dev server (e.g. it's hanging or erroring on startup). Switching branches is an intentional, deliberate action that happens to look the same from a pure timing perspective. Capturing it as rage-restart pollutes telemetry and could trigger unwanted recovery behaviour.
The git helper consolidation removes duplicated
spawnSync/execSynccalls spread across unrelated files, centralises theVERCEL_GIT_*env-var fallback logic, and makes it easy to add further git queries in one place.How?
writeDevState()innext-dev.tsnow callsgetGitBranch(dir)and stores the result under agitBranchkey in the dev state file (omitted when the branch is unknown).gitBranchis compared to the freshly-readgetGitBranch(dir).isRageRestartis only set when the branch either hasn't changed or couldn't be determined.packages/next/src/lib/helpers/git.tsprovidesgitExec()(private),getGitBranch(), andgetGitCommit(). It replaces the deletedget-git-branch.tsand the open-codedchild_process.spawnSynccalls intrace-uploader.ts.