diff --git a/pkg/gui/controllers/basic_commits_controller.go b/pkg/gui/controllers/basic_commits_controller.go index 740d326991a..47160080904 100644 --- a/pkg/gui/controllers/basic_commits_controller.go +++ b/pkg/gui/controllers/basic_commits_controller.go @@ -285,19 +285,7 @@ func (self *BasicCommitsController) checkout(commit *models.Commit) error { return commit.Hash == branch.CommitHash && branch.Name != self.c.Model().CheckedOutBranch }) - if len(commitBranches) > 0 { - return self.c.Helpers().Refs.CreateCheckoutMenu(commit.Hash, commitBranches) - } - - self.c.Confirm(types.ConfirmOpts{ - Title: self.c.Tr.CheckoutCommit, - Prompt: self.c.Tr.SureCheckoutThisCommit, - HandleConfirm: func() error { - self.c.LogAction(self.c.Tr.Actions.CheckoutCommit) - return self.c.Helpers().Refs.CheckoutRef(commit.Hash, types.CheckoutRefOptions{}) - }, - }) - return nil + return self.c.Helpers().Refs.CreateCheckoutMenu(commit.Hash, commitBranches) } func (self *BasicCommitsController) copyRange(*models.Commit) error { diff --git a/pkg/gui/controllers/helpers/refs_helper.go b/pkg/gui/controllers/helpers/refs_helper.go index 92f1a9c75d0..3a151f326c4 100644 --- a/pkg/gui/controllers/helpers/refs_helper.go +++ b/pkg/gui/controllers/helpers/refs_helper.go @@ -273,26 +273,10 @@ func (self *RefsHelper) CreateGitResetMenu(ref string) error { } func (self *RefsHelper) CreateCheckoutMenu(ref string, branches []*models.Branch) error { - menuItems := lo.Map(branches, func(branch *models.Branch, _ int) *types.MenuItem { - return &types.MenuItem{ - LabelColumns: []string{branch.Name}, - OnPress: func() error { - self.c.LogAction(self.c.Tr.Actions.CheckoutBranch) - if err := self.c.Git().Branch.Checkout(branch.Name, git_commands.CheckoutOptions{}); err != nil { - return err - } - return self.c.WithWaitingStatus(self.c.Tr.LoadingCommits, func(gocui.Task) error { - return self.c.Refresh( - types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.COMMITS}}, - ) - }) - }, - Tooltip: self.c.Tr.CheckoutBranchTooltip, - } - }) + var menuItems []*types.MenuItem menuItems = append(menuItems, &types.MenuItem{ - LabelColumns: []string{ref}, + LabelColumns: []string{fmt.Sprintf("%s %s: %s", self.c.Tr.CheckoutCommit, self.c.Tr.AsDetachedHead, ref[:7])}, OnPress: func() error { self.c.Confirm(types.ConfirmOpts{ Title: self.c.Tr.CheckoutCommit, @@ -305,8 +289,36 @@ func (self *RefsHelper) CreateCheckoutMenu(ref string, branches []*models.Branch return nil }, Tooltip: self.c.Tr.CheckoutCommitTooltip, + Key: 'd', }) + if len(branches) > 0 { + menuItems = lo.Map(branches, func(branch *models.Branch, index int) *types.MenuItem { + return &types.MenuItem{ + LabelColumns: []string{fmt.Sprintf("%s: %s", self.c.Tr.Actions.CheckoutBranch, branch.Name)}, + OnPress: func() error { + self.c.LogAction(self.c.Tr.Actions.CheckoutBranch) + if err := self.c.Git().Branch.Checkout(branch.Name, git_commands.CheckoutOptions{}); err != nil { + return err + } + return self.c.WithWaitingStatus(self.c.Tr.LoadingCommits, func(gocui.Task) error { + return self.c.Refresh( + types.RefreshOptions{Mode: types.SYNC, Scope: []types.RefreshableView{types.COMMITS}}, + ) + }) + }, + Tooltip: self.c.Tr.CheckoutBranchTooltip, + Key: rune(index + 1 + '0'), // Convert 1-based index to key + } + }) + } else { + menuItems = append(menuItems, &types.MenuItem{ + LabelColumns: []string{style.FgDefault.SetStrikethrough().Sprint(self.c.Tr.Actions.CheckoutBranch)}, + OnPress: func() error { return nil }, + DisabledReason: &types.DisabledReason{Text: self.c.Tr.NoBranchesFoundAtCommitTooltip}, + }) + } + return self.c.Menu(types.CreateMenuOptions{ Title: self.c.Tr.Actions.CheckoutBranchOrCommit, Items: menuItems, diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go index baf234249d1..a92c9380315 100644 --- a/pkg/i18n/english.go +++ b/pkg/i18n/english.go @@ -130,6 +130,7 @@ type TranslationSet struct { CheckoutTypeNewBranchTooltip string CheckoutTypeDetachedHead string CheckoutTypeDetachedHeadTooltip string + AsDetachedHead string NewBranch string NewBranchFromStashTooltip string NoBranchesThisRepo string @@ -524,6 +525,7 @@ type TranslationSet struct { CheckoutCommit string CheckoutCommitTooltip string CheckoutBranchTooltip string + NoBranchesFoundAtCommitTooltip string SureCheckoutThisCommit string GitFlowOptions string NotAGitFlowBranch string @@ -1123,6 +1125,7 @@ func EnglishTranslationSet() *TranslationSet { CheckoutTypeNewBranchTooltip: "Checkout the remote branch as a local branch, tracking the remote branch.", CheckoutTypeDetachedHead: "Detached head", CheckoutTypeDetachedHeadTooltip: "Checkout the remote branch as a detached head, which can be useful if you just want to test the branch but not work on it yourself. You can still create a local branch from it later.", + AsDetachedHead: "as detached head", NewBranch: "New branch", NewBranchFromStashTooltip: "Create a new branch from the selected stash entry. This works by git checking out the commit that the stash entry was created from, creating a new branch from that commit, then applying the stash entry to the new branch as an additional commit.", NoBranchesThisRepo: "No branches for this repo", @@ -1516,22 +1519,23 @@ func EnglishTranslationSet() *TranslationSet { DeleteRemoteTagPrompt: "Are you sure you want to delete the remote tag '{{.tagName}}' from '{{.upstream}}'?", PushTagTitle: "Remote to push tag '{{.tagName}}' to:", // Using 'push tag' rather than just 'push' to disambiguate from a global push - PushTag: "Push tag", - PushTagTooltip: "Push the selected tag to a remote. You'll be prompted to select a remote.", - NewTag: "New tag", - NewTagTooltip: "Create new tag from current commit. You'll be prompted to enter a tag name and optional description.", - CreatingTag: "Creating tag", - ForceTag: "Force Tag", - ForceTagPrompt: "The tag '{{.tagName}}' exists already. Press {{.cancelKey}} to cancel, or {{.confirmKey}} to overwrite.", - FetchRemoteTooltip: "Fetch updates from the remote repository. This retrieves new commits and branches without merging them into your local branches.", - FetchingRemoteStatus: "Fetching remote", - CheckoutCommit: "Checkout commit", - CheckoutCommitTooltip: "Checkout the selected commit as a detached HEAD.", - CheckoutBranchTooltip: "Checkout the selected branch.", - SureCheckoutThisCommit: "Are you sure you want to checkout this commit?", - GitFlowOptions: "Show git-flow options", - NotAGitFlowBranch: "This does not seem to be a git flow branch", - NewGitFlowBranchPrompt: "New {{.branchType}} name:", + PushTag: "Push tag", + PushTagTooltip: "Push the selected tag to a remote. You'll be prompted to select a remote.", + NewTag: "New tag", + NewTagTooltip: "Create new tag from current commit. You'll be prompted to enter a tag name and optional description.", + CreatingTag: "Creating tag", + ForceTag: "Force Tag", + ForceTagPrompt: "The tag '{{.tagName}}' exists already. Press {{.cancelKey}} to cancel, or {{.confirmKey}} to overwrite.", + FetchRemoteTooltip: "Fetch updates from the remote repository. This retrieves new commits and branches without merging them into your local branches.", + FetchingRemoteStatus: "Fetching remote", + CheckoutCommit: "Checkout commit", + CheckoutCommitTooltip: "Checkout the selected commit as a detached HEAD.", + CheckoutBranchTooltip: "Checkout the selected branch.", + NoBranchesFoundAtCommitTooltip: "No branches found at selected commit.", + SureCheckoutThisCommit: "Are you sure you want to checkout this commit?", + GitFlowOptions: "Show git-flow options", + NotAGitFlowBranch: "This does not seem to be a git flow branch", + NewGitFlowBranchPrompt: "New {{.branchType}} name:", IgnoreTracked: "Ignore tracked file", IgnoreTrackedPrompt: "Are you sure you want to ignore a tracked file?",