Repository navigation
Improve bisecting - #6168
Merged
Merged
Improve bisecting#6168
Conversation
`git bisect start` takes the bad commit first and the good one second. The parameters were named the other way round. The only caller already passes the bad commit first, so only the names were wrong. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The commits refresh updated the model and the selection in one hop to the UI thread, and re-rendered the view in a second one. The scroll behavior of the re-render was fixed when the refresh started. The next commit makes the scroll behavior depend on how the refresh changed the selection. Do both in one hop, so that the re-render can see that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lict If a rebase started outside of lazygit stops with a conflict, the next background refresh selects the conflicted commit. It keeps the scroll position though, so if there are enough pending todos above the conflicted commit, the selection is off-screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When a refresh finds a new conflicted commit, it selects it so that the user sees where the rebase stopped. A background refresh keeps the scroll position of the views it updates though. If the conflicted commit is outside the visible part of the commits view, the selection moves to a commit that the user can't see. Scroll the selection into view whenever the refresh moves it to a newly conflicted commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
If lazygit starts while a bisect is in progress, the commits view selects the top commit, and the user has to look for the commit that git wants them to test. The same happens when a git bisect command run outside of lazygit moves the bisect on. The bisect menu selected the new current commit after a good, bad or skip, but only if the selected commit was the current one. It also needed extra logic to wait for the refresh in case the log was going to start from a different ref. Remove that, and let the commits refresh select the current commit whenever it differs from the one at the previous refresh, like it does for a newly conflicted commit. A refresh that doesn't change it leaves the selection alone. This way a background fetch doesn't move the selection back to the current commit after the user navigated away from it. Marking the current commit as good or bad while a different commit is selected now selects the new current commit too. Skipping the selected commit when it isn't the current one is an exception. Git often picks a different commit to test after that, but we keep the skipped commit selected, so that the user can go on skipping commits near it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e log Once a bisect has started, the commits view shows the log of the branch that was checked out when it started. This happens even while we don't know both a good and a bad commit yet, and git hasn't checked out anything for the user to test. If the user checks out a different branch to mark its head as bad, the commits view keeps showing the old branch, so the new branch's head isn't there to be marked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Once a bisect had started, the commits view showed the log of the branch that was checked out when it started, even while git was still waiting for a good or a bad commit. If the user checked out a different branch to mark its head as bad, its commits weren't shown. Keep showing the log of HEAD until git starts checking out commits to test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The commits and the sub-commits views had identical copies of it. A later commit changes when it loads all commits, so make it one function first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The commit loader took a flag for whether to limit the number of commits it loads, and the limit of 300 was hard-coded in it. A later commit needs to load more than that while bisecting, so let the caller pass the number. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The commits and sub-commits views load the first 300 commits, and load all of them once the user selects a commit beyond the 200th. A later commit loads more than 300 commits while bisecting, so that the commit to test is among them. If it is beyond the 200th, it would cause all commits to be loaded as soon as it gets selected. Remember how many commits the views were loaded with, and load all of them only when the selection gets within 100 commits of that number. For the views loaded with 300 commits, nothing changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The commits view loads the first 300 commits only. If the range to bisect is longer than about 600 commits, the commit that git wants the user to test is further down than that. It isn't loaded, so we can't select it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The commits view loads the first 300 commits only. If the range to bisect is longer than about 600 commits, the commit that git wants the user to test is further down than that, so it isn't shown, and we can't select it. While bisecting, count the commits in the log above the current commit, and load that many more than usual. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After marking the first commit as good or bad, the bisect menu acts on the selected commit until git knows both a good and a bad commit. Its entries call that commit the "current commit" though, as if it was the commit that git wants the user to test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One function built the menu both for when git still waits for a good or a bad commit, and for while bisecting. Its entries act on the selected commit in the first case, and on the commit that git wants the user to test in the second case. Several conditions in the function picked between the two. The next commits change the first menu only, so make it a function of its own. Extract the menu entries that both menus have, so that they don't get duplicated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After marking the first commit as good or bad, the bisect menu's entries act on the selected commit until git knows both a good and a bad commit. They called it the "current commit" though, as if it was the commit that git wants the user to test. Call it "commit <hash>" instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It worked with the commits of the local commits context only. The next commit offers the bisect menu in other views too, such as branches and tags, so let it take any context and act on its selected ref. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
To start a bisect, users often know that one branch or tag is good and
another one is bad. The bisect menu was available in the commits panel
only, though. To mark the head of another branch, the user had to check
it out first, or find its head commit in the commits panel. The commits
panel shows only the checked-out branch.
Offer the menu in the local branches, remote branches, tags, sub-commits
and reflog views too. There it marks the selected item as good or bad,
and its entries name the item ("branch 'dev'", "tag 'v1.0'"), so that
it's clear what they act on. Once git knows both a good and a bad
commit, the bisect continues in the commits panel. It shows the good and
bad commits and the one to test next, and its menu acts on that one. So
focus the commits panel when a mark in another view gives git the second
of the two, and disable the key in the other views from then on. They
don't offer skipping either.
Name the selected commit "commit <hash>" in the commits panel's menu
too, so that it reads the same in all views.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lazygit starts in the files panel. During a bisect, this is rarely what the user needs. The commits panel shows how far the bisect has got, and the user marks the commits to test there. So start in the commits panel if a bisect is in progress, even if git doesn't know both a good and a bad commit yet. The same applies the first time the user switches to such a repo during a session. A filter path or a "status", "branch", "log" or "stash" argument still decides which panel to focus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… commit When the user marks the last commit to test as good, git reports the commit that is marked bad as the first bad commit. The commits view keeps the commit that the user just marked selected, though, so the user has to look for the result. The same happens when lazygit starts after a bisect has finished. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When the user marks the last commit to test, the commits view keeps it selected, and the user has to look for the result. The same happens when lazygit starts after a bisect has finished. After a mark, git checks out the next commit to test, unless there's nothing left to test. In that case, the commit that the user marked last is still the current commit, and the commit marked bad is the first bad commit. So once the current commit is marked, select the commit marked bad instead. Do the same if git never checked out a commit to test, because the good commit is a parent of the bad one. If only skipped commits are left to test, the first bad commit is either one of them or the commit marked bad. Select the commit marked bad then too; it's the newest of the candidates. The commits view loads the commits down to the commit that it selects, so this one is always loaded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rent" Once git has nothing left to test, the commit that the user marked last stays the current commit. The commits view labels it "<-- current", although it is marked good or bad now, and git doesn't want the user to test it any more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Once git has nothing left to test, the commit that the user marked last stays the current commit. The commits view labels it "<-- current", although git doesn't want the user to test it any more. Show its mark instead, like for the other marked commits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…done Once git has nothing left to test, the bisect menu still offers marking or skipping the current commit, although the user has marked it already. This also happens if git stopped because the merge base of the good and the bad commit is bad. If git found the first bad commit without checking out anything to test, the menu acts on the selected commit, as if git didn't know both a good and a bad commit yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Once git has nothing left to test, the bisect menu offers marking or skipping the current commit, although the user has marked it already. If git found the first bad commit without checking out anything to test, the menu acts on the selected commit instead, as if git didn't know both a good and a bad commit yet. At this point, the user wants to see the result and reset the bisect. Show the "Bisect complete" dialog again instead of the menu. It names the first bad commit and asks whether to reset the bisect. This also lets the user see the result again after declining the reset when the bisect finished. If git stopped without finding the first bad commit, because the merge base of the good and the bad commit is bad, show the confirmation for resetting the bisect. Git said why it stopped when it did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The commits view marks the commits between the bad commit and the first good commit in the list with a "?". If there's no good commit in the list, it doesn't mark any. This is the case while git tests the merge base of a good and a bad commit on different branches. It's also the case early in a long bisect, when the good commit is further down than the commits that we load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The commits view marks the commits that a bisect hasn't ruled out yet with a "?". To find them, it looks for the bad commit and the first good commit in the list, and marks the commits between them. If there's no good commit in the list, it marks none. This is the case while git tests the merge base of a good and a bad commit on different branches. It's also the case early in a long bisect, when the good commit is further down than the commits that we load. With merges, the commits between the two can also include some that the bisect has ruled out. Ask git instead, with "git rev-list <bad> --not <good>...", when refreshing the commits while git knows both a good and a bad commit. This takes about as long as the git log that loads the commits, or less, and it gets faster as the bisect goes on. Keep only the commits that the commits view has loaded, because git may list many more. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 31, 2026
Closed
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.
This PR makes bisecting easier in several ways:
b) is now also available in the local branches, remote branches, tags, sub-commits and reflog views. This makes it possible to mark a branch or tag as good or bad without checking it out first. Once git knows both a good and a bad commit, lazygit focuses the commits panel, where the bisect continues.git bisectcommands in a terminal, and when the commit is further down than the commits that lazygit loads at first.bafterwards shows the result again and offers to reset the bisect. Before, the menu offered to mark the commit that you had just marked.Closes #2346.
Closes #2941.
Closes #5530.
Closes #6103.