Prevent staging from becoming slower over time#5712
Merged
Conversation
This can be used to add a git argument that goes before the git subcommand.
We set GIT_OPTIONAL_LOCKS=0 for every git command we run. That env var only affects `git status`: it tells git not to take the optional lock it would otherwise use to write the index back after refreshing the cached stat information. The intent was to avoid contending for index.lock with git commands the user runs in a terminal. The downside is that our `git status` never persists the refreshed stat-cache. So whenever the working tree's cached stat info goes stale (e.g. editing files and discarding the changes, or a checkout), every subsequent status re-hashes the affected files to confirm they're clean, and stays slow until something else writes the index (such as the user running `git status` in a terminal). Fix this by only suppressing optional locks for refreshes that run unattended in the background; foreground refreshes triggered by a user action now run a plain `git status` that writes the refreshed index back, just like the command line does. Background refreshes keep passing --no-optional-locks so they still can't cause lock contention. RefreshOptions gains a Background flag that the background routines set, threaded down to the status command. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The wrapper existed to add a git-specific env var to every command. Now that that's gone, its New/NewShell/Quote methods just delegated to the inner builder. The only remaining git-specific behavior — the command runner — is attached in the constructor via CloneWithNewRunner, which already returns a complete builder, so we can return that directly and drop the wrapper struct. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
In a large repo, when touching (editing) more and more files, staging hunks in lazygit could become slower and slower over time. Specifically, this happened when you edited a lot of files and then discarded their changes again. I have seen cases where staging a hunk began to take seconds; the fix then was to type
git statuson the command line once, this made it fast again.The reason was that lazygit was trying too hard to be a good git citizen, and used the
GIT_OPTIONAL_LOCKS=0env var on every git command it made. The consequence was that it never updated the mod date cache in git's index file, which caused git to rehash every file whose mod date doesn't match what it recorded in the index, on every refresh. Typinggit statusupdates that cache, which is why this was a workaround.Fix this by using the
GIT_OPTIONAL_LOCKS=0flag only for refreshes that are running unattended in the background, i.e. the periodic autoRefresh and the newly external change detection. For those it is important because it avoids "cannot lock index" errors for commands that the user might issue at the same time. All other refreshes are user initiated and no longer use the flag, which is in line with whatgit statusdoes, so this keeps performance from deteriorating over time.