Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pkg/commands/git_commands/bisect.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ func (self *BisectCommands) GetInfoForGitDir(gitDir string) *BisectInfo {
return info
}

// Get actual HEAD hash to detect when user manually checked out a different commit
headHash, err := self.cmd.New(NewGitCmd("rev-parse").Arg("HEAD").ToArgv()).DontLog().RunWithOutput()
if err == nil {
info.head = strings.TrimSpace(headHash)
}

startContent, err := os.ReadFile(bisectStartPath)
if err != nil {
self.Log.Infof("error getting git bisect info: %s", err.Error())
Expand Down
7 changes: 7 additions & 0 deletions pkg/commands/git_commands/bisect_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ type BisectInfo struct {

// the hash of the commit that's under test
current string

// the actual HEAD hash (may differ from current if user manually checked out a different commit)
head string
}

type BisectStatus int
Expand Down Expand Up @@ -63,6 +66,10 @@ func (self *BisectInfo) GetCurrentHash() string {
return self.current
}

func (self *BisectInfo) GetHeadHash() string {
return self.head
}

func (self *BisectInfo) GetStartHash() string {
return self.start
}
Expand Down
14 changes: 13 additions & 1 deletion pkg/gui/presentation/commits.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,8 @@ const (
BisectStatusCandidate
// also adding this
BisectStatusCurrent
// BisectStatusHead is shown when user manually checks out a different commit during bisect
BisectStatusHead
)

func getBisectStatus(index int, commitHash string, bisectInfo *git_commands.BisectInfo, bisectBounds *bisectBounds) BisectStatus {
Expand All @@ -291,6 +293,13 @@ func getBisectStatus(index int, commitHash string, bisectInfo *git_commands.Bise
return BisectStatusCurrent
}

// Check if this is the HEAD commit when it differs from the bisect expected commit
// This helps users see where they are when they manually checkout during bisect
headHash := bisectInfo.GetHeadHash()
if headHash != "" && headHash == commitHash && headHash != bisectInfo.GetCurrentHash() {
return BisectStatusHead
}

status, ok := bisectInfo.Status(commitHash)
if ok {
switch status {
Expand Down Expand Up @@ -325,8 +334,9 @@ func getBisectStatusText(bisectStatus BisectStatus, bisectInfo *git_commands.Bis
case BisectStatusOld:
return style.Sprintf("<-- " + bisectInfo.OldTerm())
case BisectStatusCurrent:
// TODO: i18n
return style.Sprintf("<-- current")
case BisectStatusHead:
return style.Sprintf("<-- YOU ARE HERE")
case BisectStatusSkipped:
return style.Sprintf("<-- skipped")
case BisectStatusCandidate:
Expand Down Expand Up @@ -461,6 +471,8 @@ func getBisectStatusColor(status BisectStatus) style.TextStyle {
return style.FgYellow
case BisectStatusCurrent:
return style.FgMagenta
case BisectStatusHead:
return style.FgCyan
case BisectStatusCandidate:
return style.FgBlue
}
Expand Down
74 changes: 74 additions & 0 deletions pkg/integration/tests/bisect/checkout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package bisect

import (
"github.com/jesseduffield/lazygit/pkg/config"
. "github.com/jesseduffield/lazygit/pkg/integration/components"
)

var Checkout = NewIntegrationTest(NewIntegrationTestArgs{
Description: "Test checkout during bisect shows HEAD position correctly",
ExtraCmdArgs: []string{},
Skip: false,
SetupRepo: func(shell *Shell) {
shell.
NewBranch("mybranch").
CreateNCommits(10)
},
SetupConfig: func(cfg *config.AppConfig) {
cfg.GetUserConfig().Git.Log.ShowGraph = "never"
},
Run: func(t *TestDriver, keys config.KeybindingConfig) {
// Start bisect by marking commit 09 as bad and commit 02 as good
t.Views().Commits().
Focus().
SelectedLine(Contains("CI commit 10")).
NavigateToLine(Contains("CI commit 09")).
Press(keys.Commits.ViewBisectOptions)

t.ExpectPopup().Menu().Title(Equals("Bisect")).Select(MatchesRegexp(`Mark .* as bad`)).Confirm()

t.Views().Information().Content(Contains("Bisecting"))

t.Views().Commits().
IsFocused().
NavigateToLine(Contains("CI commit 02")).
Press(keys.Commits.ViewBisectOptions)

t.ExpectPopup().Menu().Title(Equals("Bisect")).Select(MatchesRegexp(`Mark .* as good`)).Confirm()

// Now we're bisecting, we should be at commit 05 (the midpoint)
t.Views().Commits().
IsFocused().
SelectedLine(Contains("CI commit 05").Contains("<-- current"))

// Try to checkout a different commit (commit 03)
t.Views().Commits().
NavigateToLine(Contains("CI commit 03")).
PressPrimaryAction()

// The checkout menu should appear
t.ExpectPopup().Menu().
Title(Contains("Checkout branch or commit")).
Select(MatchesRegexp("Checkout commit .* as detached head")).
Confirm()

// After checkout, focus moves to branches panel
t.Views().Branches().
IsFocused()

// Now go back to commits panel and verify HEAD position is shown
t.Views().Commits().
Focus().
// Commit 05 should still show "<-- current" (bisect expected)
// Commit 03 should show "<-- YOU ARE HERE" (actual HEAD position)
Content(
Contains("<-- bad").
Contains("<-- current").
Contains("<-- YOU ARE HERE").
Contains("<-- good"),
)

// Bisect should still be active
t.Views().Information().Content(Contains("Bisecting"))
},
})
1 change: 1 addition & 0 deletions pkg/integration/tests/test_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (

var tests = []*components.IntegrationTest{
bisect.Basic,
bisect.Checkout,
bisect.ChooseTerms,
bisect.FromOtherBranch,
bisect.Skip,
Expand Down