Skip to content

Improve index.lock retry mechanism - #5788

Merged
stefanhaller merged 5 commits into
v0.63.1from
improve-index.lock-retry
Jul 15, 2026
Merged

Improve index.lock retry mechanism#5788
stefanhaller merged 5 commits into
v0.63.1from
improve-index.lock-retry

Conversation

@stefanhaller

Copy link
Copy Markdown
Collaborator

In v0.63.0 we made a change to no longer use GIT_OPTIONAL_LOCKS=0 on git commands that are part of a "foreground" refresh, meaning the refresh after a lazygit command or the focus-in refresh. We do this on purpose to keep git's mod date cache from becoming stale, which could make lazygit become slower over time. However, this caused a problem for users who work very fast: staging a file and then immediately pressing shift-A to amend while the staging's refresh is still running would show the dreaded index.lock error.

We already had a retry-on-index-lock-error mechanism in place, but it wasn't used for commands like amend or commit; fix this so that the retry loop works for these too, and also make the retry window a little longer, and fix a problem where it wouldn't work in linked worktrees or submodules.

Closes #5778.

stefanhaller and others added 5 commits July 15, 2026 10:08
RunWithOutput and RunWithOutputs each carried their own near-identical
copy of the index.lock retry loop. Extract the loop into a single
retryOnLockError helper so the retry policy lives in one place, ahead of
changing that policy. Behavior is unchanged; the added tests characterize
it (success and non-lock errors run once, a lock error in the output is
retried).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The gpg helper runs commands like amend with StreamOutput, so their
output isn't captured and a failed run returns an empty output string;
the index.lock message is carried by the error instead. isRetryableError
only inspects the output, so the retry loop never fires for these
commands. In practice this means a `shift-A` amend issued while a
foreground `git status` refresh briefly holds index.lock fails outright
instead of retrying.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Have isRetryableError also inspect the returned error, not just the
captured output. Streamed commands (amend, commit, and other operations
run through the gpg helper) don't capture output, so their index.lock
failures were slipping past the retry loop and surfacing to the user as
a hard "Git command failed". Now they retry like every other command.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The retry check matched the literal ".git/index.lock", which only ever
appears for the main worktree. A linked worktree's lock is at
.git/worktrees/<name>/index.lock and a submodule's is under its own git
dir, so contention there was never retried. Match the bare "index.lock"
fragment instead, which covers all of them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The retry budget was five fixed 50ms waits (250ms total). A foreground
`git status` refresh can hold index.lock for longer than that on a large
repo, so the retries could be exhausted before the lock clears. Wait 20ms
before the first retry and double each time, giving seven attempts over a
bit more than a second — enough to outlast a slow refresh while keeping
the common case (a lock that clears almost immediately) fast. The initial
delay is now a runner field so tests can zero it out instead of sleeping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@stefanhaller
stefanhaller force-pushed the improve-index.lock-retry branch from ee7e70e to 4052057 Compare July 15, 2026 08:09
@stefanhaller
stefanhaller merged commit 9f51f04 into v0.63.1 Jul 15, 2026
12 checks passed
@stefanhaller
stefanhaller deleted the improve-index.lock-retry branch July 15, 2026 08:12
tmeijn pushed a commit to tmeijn/dotfiles that referenced this pull request Jul 17, 2026
This MR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [jesseduffield/lazygit](https://github.com/jesseduffield/lazygit) | patch | `v0.63.0` → `v0.63.1` |

MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot).

**Proposed changes to behavior should be submitted there as MRs.**

---

### Release Notes

<details>
<summary>jesseduffield/lazygit (jesseduffield/lazygit)</summary>

### [`v0.63.1`](https://github.com/jesseduffield/lazygit/releases/tag/v0.63.1)

[Compare Source](jesseduffield/lazygit@v0.63.0...v0.63.1)

<!-- Release notes generated using configuration in .github/release.yml at v0.63.1 -->

Fixes for a few regressions introduced in the v0.63.0 release.

#### What's Changed

##### Fixes 🔧

- Improve index.lock retry mechanism by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5788](jesseduffield/lazygit#5788)
- Fix userEvents panic by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5793](jesseduffield/lazygit#5793)
- Fix a deadlock on Windows when switching between longer diffs by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5815](jesseduffield/lazygit#5815)

##### Maintenance ⚙️

- Allow releasing from a branch other than master by [@&#8203;stefanhaller](https://github.com/stefanhaller) in [#&#8203;5819](jesseduffield/lazygit#5819)

**Full Changelog**: <jesseduffield/lazygit@v0.63.0...v0.63.1>

</details>

---

### Configuration

📅 **Schedule**: (UTC)

- Branch creation
  - At any time (no schedule defined)
- Automerge
  - At any time (no schedule defined)

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever MR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this MR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box

---

This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4yNjMuNiIsInVwZGF0ZWRJblZlciI6IjQzLjI2My42IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6cGF0Y2giXX0=-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant