diff --git a/pkg/gui/controllers/basic_commits_controller.go b/pkg/gui/controllers/basic_commits_controller.go
index ac0ffb394..797215746 100644
--- a/pkg/gui/controllers/basic_commits_controller.go
+++ b/pkg/gui/controllers/basic_commits_controller.go
@@ -280,15 +280,7 @@ func (self *BasicCommitsController) createResetMenu(commit *models.Commit) error
 }
 
 func (self *BasicCommitsController) checkout(commit *models.Commit) error {
-	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)
 }
 
 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 8332174dc..9fb354a8d 100644
--- a/pkg/gui/controllers/helpers/refs_helper.go
+++ b/pkg/gui/controllers/helpers/refs_helper.go
@@ -18,6 +18,7 @@ type IRefsHelper interface {
 	CheckoutRef(ref string, options types.CheckoutRefOptions) error
 	GetCheckedOutRef() *models.Branch
 	CreateGitResetMenu(ref string) error
+	CreateCheckoutMenu(commit *models.Commit) error
 	ResetToRef(ref string, strength string, envVars []string) error
 	NewBranch(from string, fromDescription string, suggestedBranchname string) error
 }
@@ -271,6 +272,53 @@ func (self *RefsHelper) CreateGitResetMenu(ref string) error {
 	})
 }
 
+func (self *RefsHelper) CreateCheckoutMenu(commit *models.Commit) error {
+	branches := lo.Filter(self.c.Model().Branches, func(branch *models.Branch, _ int) bool {
+		return commit.Hash == branch.CommitHash && branch.Name != self.c.Model().CheckedOutBranch
+	})
+
+	hash := commit.Hash
+	var menuItems []*types.MenuItem
+
+	if len(branches) > 0 {
+		menuItems = append(menuItems, lo.Map(branches, func(branch *models.Branch, index int) *types.MenuItem {
+			var key types.Key
+			if index < 9 {
+				key = rune(index + 1 + '0') // Convert 1-based index to key
+			}
+			return &types.MenuItem{
+				LabelColumns: []string{fmt.Sprintf(self.c.Tr.Actions.CheckoutBranchAtCommit, branch.Name)},
+				OnPress: func() error {
+					self.c.LogAction(self.c.Tr.Actions.CheckoutBranch)
+					return self.CheckoutRef(branch.RefName(), types.CheckoutRefOptions{})
+				},
+				Key: key,
+			}
+		})...)
+	} else {
+		menuItems = append(menuItems, &types.MenuItem{
+			LabelColumns:   []string{self.c.Tr.Actions.CheckoutBranch},
+			OnPress:        func() error { return nil },
+			DisabledReason: &types.DisabledReason{Text: self.c.Tr.NoBranchesFoundAtCommitTooltip},
+			Key:            '1',
+		})
+	}
+
+	menuItems = append(menuItems, &types.MenuItem{
+		LabelColumns: []string{fmt.Sprintf(self.c.Tr.Actions.CheckoutCommitAsDetachedHead, utils.ShortHash(hash))},
+		OnPress: func() error {
+			self.c.LogAction(self.c.Tr.Actions.CheckoutCommit)
+			return self.CheckoutRef(hash, types.CheckoutRefOptions{})
+		},
+		Key: 'd',
+	})
+
+	return self.c.Menu(types.CreateMenuOptions{
+		Title: self.c.Tr.Actions.CheckoutBranchOrCommit,
+		Items: menuItems,
+	})
+}
+
 func (self *RefsHelper) NewBranch(from string, fromFormattedName string, suggestedBranchName string) error {
 	message := utils.ResolvePlaceholderString(
 		self.c.Tr.NewBranchNameBranchOff,
diff --git a/pkg/i18n/english.go b/pkg/i18n/english.go
index 8c8ce9958..2bff2d6bd 100644
--- a/pkg/i18n/english.go
+++ b/pkg/i18n/english.go
@@ -527,6 +527,7 @@ type TranslationSet struct {
 	FetchingRemoteStatus                  string
 	CheckoutCommit                        string
 	CheckoutCommitTooltip                 string
+	NoBranchesFoundAtCommitTooltip        string
 	SureCheckoutThisCommit                string
 	GitFlowOptions                        string
 	NotAGitFlowBranch                     string
@@ -860,8 +861,11 @@ type Log struct {
 
 type Actions struct {
 	CheckoutCommit                    string
+	CheckoutBranchAtCommit            string
+	CheckoutCommitAsDetachedHead      string
 	CheckoutTag                       string
 	CheckoutBranch                    string
+	CheckoutBranchOrCommit            string
 	ForceCheckoutBranch               string
 	DeleteLocalBranch                 string
 	Merge                             string
@@ -1522,21 +1526,22 @@ 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.",
-		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.",
+		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?",
@@ -1822,9 +1827,12 @@ func EnglishTranslationSet() *TranslationSet {
 		Actions: Actions{
 			// TODO: combine this with the original keybinding descriptions (those are all in lowercase atm)
 			CheckoutCommit:                 "Checkout commit",
+			CheckoutBranchAtCommit:         "Checkout branch '%s'",
+			CheckoutCommitAsDetachedHead:   "Checkout commit %s as detached head",
 			CheckoutTag:                    "Checkout tag",
 			CheckoutBranch:                 "Checkout branch",
 			ForceCheckoutBranch:            "Force checkout branch",
+			CheckoutBranchOrCommit:         "Checkout branch or commit",
 			DeleteLocalBranch:              "Delete local branch",
 			Merge:                          "Merge",
 			SquashMerge:                    "Squash merge",
diff --git a/pkg/integration/tests/commit/checkout.go b/pkg/integration/tests/commit/checkout.go
new file mode 100644
index 000000000..455aa273c
--- /dev/null
+++ b/pkg/integration/tests/commit/checkout.go
@@ -0,0 +1,69 @@
+package commit
+
+import (
+	"github.com/jesseduffield/lazygit/pkg/config"
+	. "github.com/jesseduffield/lazygit/pkg/integration/components"
+)
+
+var Checkout = NewIntegrationTest(NewIntegrationTestArgs{
+	Description:  "Checkout a commit as a detached head, or checkout an existing branch at a commit",
+	ExtraCmdArgs: []string{},
+	Skip:         false,
+	SetupConfig:  func(config *config.AppConfig) {},
+	SetupRepo: func(shell *Shell) {
+		shell.EmptyCommit("one")
+		shell.EmptyCommit("two")
+		shell.NewBranch("branch1")
+		shell.NewBranch("branch2")
+		shell.EmptyCommit("three")
+		shell.EmptyCommit("four")
+	},
+	Run: func(t *TestDriver, keys config.KeybindingConfig) {
+		t.Views().Commits().
+			Focus().
+			Lines(
+				Contains("four").IsSelected(),
+				Contains("three"),
+				Contains("two"),
+				Contains("one"),
+			).
+			PressPrimaryAction()
+
+		t.ExpectPopup().Menu().
+			Title(Contains("Checkout branch or commit")).
+			Lines(
+				Contains("Checkout branch").IsSelected(),
+				MatchesRegexp("Checkout commit [a-f0-9]+ as detached head"),
+				Contains("Cancel"),
+			).
+			Tooltip(Contains("Disabled: No branches found at selected commit.")).
+			Select(MatchesRegexp("Checkout commit [a-f0-9]+ as detached head")).
+			Confirm()
+		t.Views().Branches().Lines(
+			Contains("* (HEAD detached at"),
+			Contains("branch2"),
+			Contains("branch1"),
+			Contains("master"),
+		)
+
+		t.Views().Commits().
+			NavigateToLine(Contains("two")).
+			PressPrimaryAction()
+
+		t.ExpectPopup().Menu().
+			Title(Contains("Checkout branch or commit")).
+			Lines(
+				Contains("Checkout branch 'branch1'").IsSelected(),
+				Contains("Checkout branch 'master'"),
+				MatchesRegexp("Checkout commit [a-f0-9]+ as detached head"),
+				Contains("Cancel"),
+			).
+			Select(Contains("Checkout branch 'master'")).
+			Confirm()
+		t.Views().Branches().Lines(
+			Contains("master"),
+			Contains("branch2"),
+			Contains("branch1"),
+		)
+	},
+})
diff --git a/pkg/integration/tests/reflog/checkout.go b/pkg/integration/tests/reflog/checkout.go
index 94ca6e7ef..90ba93a06 100644
--- a/pkg/integration/tests/reflog/checkout.go
+++ b/pkg/integration/tests/reflog/checkout.go
@@ -28,9 +28,9 @@ var Checkout = NewIntegrationTest(NewIntegrationTestArgs{
 			SelectNextItem().
 			PressPrimaryAction().
 			Tap(func() {
-				t.ExpectPopup().Confirmation().
-					Title(Contains("Checkout commit")).
-					Content(Contains("Are you sure you want to checkout this commit?")).
+				t.ExpectPopup().Menu().
+					Title(Contains("Checkout branch or commit")).
+					Select(MatchesRegexp("Checkout commit [a-f0-9]+ as detached head")).
 					Confirm()
 			}).
 			TopLines(
diff --git a/pkg/integration/tests/test_list.go b/pkg/integration/tests/test_list.go
index 782bdcb1b..2e33a4f4e 100644
--- a/pkg/integration/tests/test_list.go
+++ b/pkg/integration/tests/test_list.go
@@ -84,6 +84,7 @@ var tests = []*components.IntegrationTest{
 	commit.AddCoAuthorWhileCommitting,
 	commit.Amend,
 	commit.AutoWrapMessage,
+	commit.Checkout,
 	commit.Commit,
 	commit.CommitMultiline,
 	commit.CommitSwitchToEditor,