diff --git a/pkg/commands/git_commands/bisect.go b/pkg/commands/git_commands/bisect.go index 300613e1673..4778556168b 100644 --- a/pkg/commands/git_commands/bisect.go +++ b/pkg/commands/git_commands/bisect.go @@ -89,13 +89,27 @@ func (self *BisectCommands) GetInfoForGitDir(gitDir string) *BisectInfo { info.statusMap[hash] = status } - currentContent, err := os.ReadFile(filepath.Join(gitDir, "BISECT_EXPECTED_REV")) + // Only set current when BISECT_EXPECTED_REV exists, which indicates that git has + // started the narrowing process (both good and bad commits have been marked). + // We use HEAD instead of BISECT_EXPECTED_REV because we want to show where HEAD + // actually is, not where git bisect expects you to be. This way, if the user manually + // checks out a different commit during bisect, the UI will correctly show that commit + // as "current" instead of the bisect-expected commit. + bisectExpectedRevPath := filepath.Join(gitDir, "BISECT_EXPECTED_REV") + exists, err = self.os.FileExists(bisectExpectedRevPath) if err != nil { self.Log.Infof("error getting git bisect info: %s", err.Error()) return info } - currentHash := strings.TrimSpace(string(currentContent)) - info.current = currentHash + if exists { + cmdArgs := NewGitCmd("rev-parse").Arg("HEAD").ToArgv() + output, err := self.cmd.New(cmdArgs).DontLog().RunWithOutput() + if err != nil { + self.Log.Infof("error getting git bisect info: %s", err.Error()) + return info + } + info.current = strings.TrimSpace(output) + } return info } diff --git a/pkg/integration/tests/bisect/checkout.go b/pkg/integration/tests/bisect/checkout.go new file mode 100644 index 00000000000..9d7bdb18f61 --- /dev/null +++ b/pkg/integration/tests/bisect/checkout.go @@ -0,0 +1,78 @@ +package bisect + +import ( + "github.com/jesseduffield/lazygit/pkg/config" + . "github.com/jesseduffield/lazygit/pkg/integration/components" +) + +var Checkout = NewIntegrationTest(NewIntegrationTestArgs{ + Description: "Start a git bisect and checkout a different commit within the bisect range", + ExtraCmdArgs: []string{}, + Skip: false, + SetupRepo: func(shell *Shell) { + shell. + CreateNCommits(10) + }, + SetupConfig: func(cfg *config.AppConfig) { + cfg.GetUserConfig().Git.Log.ShowGraph = "never" + }, + Run: func(t *TestDriver, keys config.KeybindingConfig) { + t.Views().Commits(). + Focus(). + SelectedLine(Contains("commit 10")). + Press(keys.Commits.ViewBisectOptions). + Tap(func() { + t.ExpectPopup().Menu().Title(Equals("Bisect")).Select(MatchesRegexp(`Mark .* as bad`)).Confirm() + }). + NavigateToLine(Contains("commit 01")). + Press(keys.Commits.ViewBisectOptions). + Tap(func() { + t.ExpectPopup().Menu().Title(Equals("Bisect")).Select(MatchesRegexp(`Mark .* as good`)).Confirm() + t.Views().Information().Content(Contains("Bisecting")) + }). + // Verify we're at the bisect-selected commit (commit 05) + Lines( + Contains("CI commit 10").Contains("<-- bad"), + Contains("CI commit 09").DoesNotContain("<--"), + Contains("CI commit 08").DoesNotContain("<--"), + Contains("CI commit 07").DoesNotContain("<--"), + Contains("CI commit 06").DoesNotContain("<--"), + Contains("CI commit 05").Contains("<-- current").IsSelected(), + Contains("CI commit 04").DoesNotContain("<--"), + Contains("CI commit 03").DoesNotContain("<--"), + Contains("CI commit 02").DoesNotContain("<--"), + Contains("CI commit 01").Contains("<-- good"), + ). + // Navigate to a different commit and checkout + NavigateToLine(Contains("commit 07")). + PressPrimaryAction() + + // Confirm the checkout menu and select detached head checkout + t.ExpectPopup().Menu(). + Title(Contains("Checkout branch or commit")). + Select(MatchesRegexp("Checkout commit .* as detached head")). + Confirm() + + // After checkout, focus switches to branches panel - just verify it's focused + t.Views().Branches(). + IsFocused() + + // Switch back to commits panel and verify the current marker moved + t.Views().Commits(). + Focus(). + Lines( + Contains("CI commit 10").Contains("<-- bad"), + Contains("CI commit 09").DoesNotContain("<--"), + Contains("CI commit 08").DoesNotContain("<--"), + // The current marker should now be on commit 07 (where HEAD is), + // not on commit 05 (where bisect expected us to be) + Contains("CI commit 07").Contains("<-- current"), + Contains("CI commit 06").DoesNotContain("<--"), + Contains("CI commit 05").DoesNotContain("<--"), + Contains("CI commit 04").DoesNotContain("<--"), + Contains("CI commit 03").DoesNotContain("<--"), + Contains("CI commit 02").DoesNotContain("<--"), + Contains("CI commit 01").Contains("<-- good"), + ) + }, +}) diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go index f19d5aef333..6107deac454 100644 --- a/pkg/integration/tests/test_list.go +++ b/pkg/integration/tests/test_list.go @@ -36,6 +36,7 @@ import ( var tests = []*components.IntegrationTest{ bisect.Basic, + bisect.Checkout, bisect.ChooseTerms, bisect.FromOtherBranch, bisect.Skip,