Repository: git-town/git-town

Issue:
switch: crashes when combinging --display-types and --all
### Steps to reproduce

git-town switch --display-types --all

### Command output

```shell
Caught panic:

unhandled branch type () for branch "kg-video-tools"

Restoring terminal...

goroutine 1 [running]:
runtime/debug.Stack()
        /usr/lib/golang/src/runtime/debug/stack.go:26 +0x64
runtime/debug.PrintStack()
        /usr/lib/golang/src/runtime/debug/stack.go:18 +0x1c
github.com/charmbracelet/bubbletea.(*Program).recoverFromPanic(0x400015aa00, {0x85ec80, 0x40002be970})
        /home/kevlar/git-town/vendor/github.com/charmbracelet/bubbletea/tea.go:810 +0xa0
github.com/charmbracelet/bubbletea.(*Program).Run.func2()
        /home/kevlar/git-town/vendor/github.com/charmbracelet/bubbletea/tea.go:601 +0xdc
panic({0x85ec80?, 0x40002be970?})
        /usr/lib/golang/src/runtime/panic.go:792 +0x124
github.com/git-town/git-town/v22/internal/cli/dialog.ShouldDisplayBranchType({0x0?, 0x0?}, {0x40002cfb39, 0xe})
        /home/kevlar/git-town/internal/cli/dialog/switch_branch.go:267 +0x1f4
github.com/git-town/git-town/v22/internal/cli/dialog.SwitchModel.View({{{{0x2, {...}, {...}}, {0x2, {...}, {...}}, {0x2, {...}, {...}}, {0x2, ...}, ...}, ...}, ...})
        /home/kevlar/git-town/internal/cli/dialog/switch_branch.go:139 +0xe30
github.com/charmbracelet/bubbletea.(*Program).Run(0x400015aa00)
        /home/kevlar/git-town/vendor/github.com/charmbracelet/bubbletea/tea.go:663 +0x7bc
github.com/git-town/git-town/v22/internal/cli/dialog.SwitchBranch({{0x40002be890}, 0x2, 0x1, {0x40002de008, 0xc, 0x12}, {{0x40002a7188, 0xc, 0x12}, {0x134d660, ...}, ...}, ...})
        /home/kevlar/git-town/internal/cli/dialog/switch_branch.go:284 +0x438
github.com/git-town/git-town/v22/internal/cmd.executeSwitch({0x1, {0x400007dd80, 0x0, 0x2}, {0x134d660, 0x0, 0x0}, {0x400023a690, {0x0}, {0x0}, ...}, ...})
        /home/kevlar/git-town/internal/cmd/switch.go:126 +0x560
github.com/git-town/git-town/v22/internal/cmd.switchCmd.func1(0x4000238f08, {0x400007dd80, 0x0, 0x2})
        /home/kevlar/git-town/internal/cmd/switch.go:58 +0x2c4
github.com/spf13/cobra.(*Command).execute(0x4000238f08, {0x400007dd60, 0x2, 0x2})
        /home/kevlar/git-town/vendor/github.com/spf13/cobra/command.go:1015 +0x844
github.com/spf13/cobra.(*Command).ExecuteC(0x400021e008)
        /home/kevlar/git-town/vendor/github.com/spf13/cobra/command.go:1148 +0x384
github.com/spf13/cobra.(*Command).Execute(...)
        /home/kevlar/git-town/vendor/github.com/spf13/cobra/command.go:1071
github.com/git-town/git-town/v22/internal/cmd.Execute()
        /home/kevlar/git-town/internal/cmd/doc.go:49 +0x434
main.main()
        /home/kevlar/git-town/main.go:18 +0x28
panic: interface conversion: tea.Model is nil, not dialog.SwitchModel

goroutine 1 [running]:
github.com/git-town/git-town/v22/internal/cli/dialog.SwitchBranch({{0x40002be890}, 0x2, 0x1, {0x40002de008, 0xc, 0x12}, {{0x40002a7188, 0xc, 0x12}, {0x134d660, ...}, ...}, ...})
        /home/kevlar/git-town/internal/cli/dialog/switch_branch.go:285 +0x59c
github.com/git-town/git-town/v22/internal/cmd.executeSwitch({0x1, {0x400007dd80, 0x0, 0x2}, {0x134d660, 0x0, 0x0}, {0x400023a690, {0x0}, {0x0}, ...}, ...})
        /home/kevlar/git-town/internal/cmd/switch.go:126 +0x560
github.com/git-town/git-town/v22/internal/cmd.switchCmd.func1(0x4000238f08, {0x400007dd80, 0x0, 0x2})
        /home/kevlar/git-town/internal/cmd/switch.go:58 +0x2c4
github.com/spf13/cobra.(*Command).execute(0x4000238f08, {0x400007dd60, 0x2, 0x2})
        /home/kevlar/git-town/vendor/github.com/spf13/cobra/command.go:1015 +0x844
github.com/spf13/cobra.(*Command).ExecuteC(0x400021e008)
        /home/kevlar/git-town/vendor/github.com/spf13/cobra/command.go:1148 +0x384
github.com/spf13/cobra.(*Command).Execute(...)
        /home/kevlar/git-town/vendor/github.com/spf13/cobra/command.go:1071
github.com/git-town/git-town/v22/internal/cmd.Execute()
        /home/kevlar/git-town/internal/cmd/doc.go:49 +0x434
main.main()
        /home/kevlar/git-town/main.go:18 +0x28
```

### Additional information

_No response_

Hints from issue comments:
@kevgo: This is now available in [v22.2](https://github.com/git-town/git-town/releases/tag/v22.2.0).

Solution patch:
diff --git a/features/switch/all_flag/all_flag.feature b/features/switch/all_flag/all_flag.feature
index 453a26b5f..87c95806b 100644
--- a/features/switch/all_flag/all_flag.feature
+++ b/features/switch/all_flag/all_flag.feature
@@ -1,7 +1,7 @@
 @messyoutput
 Feature: switch to a new remote branch
 
-  Scenario Outline:
+  Scenario Outline: flag variations
     Given a Git repo with origin
     And the branches
       | NAME     | TYPE    | PARENT | LOCATIONS     |
@@ -21,3 +21,19 @@ Feature: switch to a new remote branch
       | FLAG  |
       | --all |
       | -a    |
+
+  Scenario: combine with --display-types
+    Given a Git repo with origin
+    And the branches
+      | NAME     | TYPE    | PARENT | LOCATIONS     |
+      | local-1  | feature | main   | local, origin |
+      | local-2  | feature | main   | local, origin |
+      | remote-1 | feature | main   | origin        |
+    And the current branch is "local-2"
+    And I ran "git fetch"
+    When I run "git-town switch --all --display-types" and enter into the dialogs:
+      | DIALOG        | KEYS            |
+      | switch-branch | down down enter |
+    Then Git Town runs the commands
+      | BRANCH  | COMMAND               |
+      | local-2 | git checkout remote-1 |
diff --git a/internal/cmd/append.go b/internal/cmd/append.go
index c96d755f0..ac21f3dbe 100644
--- a/internal/cmd/append.go
+++ b/internal/cmd/append.go
@@ -322,7 +322,7 @@ func determineAppendData(args determineAppendDataArgs, repo execute.OpenRepoResu
 	if !hasInitialBranchInfo {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
 	}
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	validatedConfig, exit, err := validate.Config(validate.ConfigArgs{
 		Backend:            repo.Backend,
 		BranchInfos:        branchesSnapshot.Branches,
@@ -333,7 +333,7 @@ func determineAppendData(args determineAppendDataArgs, repo execute.OpenRepoResu
 		Frontend:           repo.Frontend,
 		Git:                repo.Git,
 		Inputs:             inputs,
-		LocalBranches:      branchesSnapshot.Branches.LocalBranches().Names(),
+		LocalBranches:      branchesSnapshot.Branches.LocalBranches().NamesLocalBranches(),
 		Remotes:            remotes,
 		RepoStatus:         repoStatus,
 		Unvalidated:        NewMutable(&repo.UnvalidatedConfig),
diff --git a/internal/cmd/branch.go b/internal/cmd/branch.go
index f04def75a..d8d4bc042 100644
--- a/internal/cmd/branch.go
+++ b/internal/cmd/branch.go
@@ -137,7 +137,7 @@ func determineBranchData(repo execute.OpenRepoResult) (data branchData, flow con
 		}
 	}
 	colors := dialogcolors.NewDialogColors()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.Names())
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.NamesLocalBranches())
 	return branchData{
 		branchInfos:      branchesSnapshot.Branches,
 		branchesAndTypes: branchesAndTypes,
diff --git a/internal/cmd/compress.go b/internal/cmd/compress.go
index b3c58cd7a..1c028c7f0 100644
--- a/internal/cmd/compress.go
+++ b/internal/cmd/compress.go
@@ -241,8 +241,8 @@ func determineCompressData(repo execute.OpenRepoResult, message Option[gitdomain
 	if !hasInitialBranch {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/continue.go b/internal/cmd/continue.go
index 8c5813c0c..f5746972e 100644
--- a/internal/cmd/continue.go
+++ b/internal/cmd/continue.go
@@ -154,8 +154,8 @@ func determineContinueData(repo execute.OpenRepoResult) (data continueData, flow
 	case configdomain.ProgramFlowExit, configdomain.ProgramFlowRestart:
 		return data, flow, nil
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/delete.go b/internal/cmd/delete.go
index c006d2b07..0b3bf53b3 100644
--- a/internal/cmd/delete.go
+++ b/internal/cmd/delete.go
@@ -242,8 +242,8 @@ func determineDeleteData(args []string, repo execute.OpenRepoResult) (data delet
 	if branchToDeleteInfo.SyncStatus == gitdomain.SyncStatusOtherWorktree {
 		return data, configdomain.ProgramFlowExit, fmt.Errorf(messages.BranchOtherWorktree, branchToDelete)
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/detach.go b/internal/cmd/detach.go
index 793f3e356..c19f65bed 100644
--- a/internal/cmd/detach.go
+++ b/internal/cmd/detach.go
@@ -250,8 +250,8 @@ func determineDetachData(repo execute.OpenRepoResult) (data detachData, flow con
 	if branchToDetachInfo.SyncStatus == gitdomain.SyncStatusOtherWorktree {
 		return data, configdomain.ProgramFlowExit, fmt.Errorf(messages.BranchOtherWorktree, branchNameToDetach)
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/diff_parent.go b/internal/cmd/diff_parent.go
index ab57e1799..03c8e2d96 100644
--- a/internal/cmd/diff_parent.go
+++ b/internal/cmd/diff_parent.go
@@ -158,8 +158,8 @@ func determineDiffParentData(args []string, repo execute.OpenRepoResult) (data d
 			return data, configdomain.ProgramFlowExit, fmt.Errorf(messages.BranchDoesntExist, branch)
 		}
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/hack.go b/internal/cmd/hack.go
index 90fb9dc6d..2c612cb44 100644
--- a/internal/cmd/hack.go
+++ b/internal/cmd/hack.go
@@ -261,7 +261,7 @@ func determineHackData(args hackArgs, repo execute.OpenRepoResult) (data appendF
 	case configdomain.ProgramFlowExit, configdomain.ProgramFlowRestart:
 		return data, flow, nil
 	}
-	localBranchNames := branchesSnapshot.Branches.LocalBranches().Names()
+	localBranchNames := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
 	initialBranch, hasInitialBranch := branchesSnapshot.Active.Get()
 	if !hasInitialBranch {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
diff --git a/internal/cmd/init.go b/internal/cmd/init.go
index caef209cd..e028e9911 100644
--- a/internal/cmd/init.go
+++ b/internal/cmd/init.go
@@ -139,7 +139,7 @@ func LoadData(repo execute.OpenRepoResult) (data setup.Data, flow configdomain.P
 		Config:        repo.UnvalidatedConfig,
 		Git:           repo.Git,
 		Inputs:        inputs,
-		LocalBranches: branchesSnapshot.Branches.LocalBranches().Names(),
+		LocalBranches: branchesSnapshot.Branches.LocalBranches().NamesLocalBranches(),
 		Remotes:       remotes,
 		Snapshot:      repo.ConfigSnapshot,
 	}, configdomain.ProgramFlowContinue, nil
diff --git a/internal/cmd/merge.go b/internal/cmd/merge.go
index e76b512f1..996a886c7 100644
--- a/internal/cmd/merge.go
+++ b/internal/cmd/merge.go
@@ -230,8 +230,8 @@ func determineMergeData(repo execute.OpenRepoResult) (data mergeData, flow confi
 	if !hasInitialBranch {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
 	}
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/prepend.go b/internal/cmd/prepend.go
index ad0daa63f..323476de4 100644
--- a/internal/cmd/prepend.go
+++ b/internal/cmd/prepend.go
@@ -327,7 +327,7 @@ func determinePrependData(args prependArgs, repo execute.OpenRepoResult) (data p
 	if branchesSnapshot.Branches.HasMatchingTrackingBranchFor(targetBranch, repo.UnvalidatedConfig.NormalConfig.DevRemote) {
 		return data, configdomain.ProgramFlowExit, fmt.Errorf(messages.BranchAlreadyExistsRemotely, targetBranch)
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
 	initialBranch, hasInitialBranch := branchesSnapshot.Active.Get()
 	if !hasInitialBranch {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
@@ -336,7 +336,7 @@ func determinePrependData(args prependArgs, repo execute.OpenRepoResult) (data p
 	if !hasInitialBranchInfo {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
 	}
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	validatedConfig, exit, err := validate.Config(validate.ConfigArgs{
 		Backend:            repo.Backend,
 		BranchInfos:        branchesSnapshot.Branches,
diff --git a/internal/cmd/propose.go b/internal/cmd/propose.go
index c88e8fe14..4f1484d84 100644
--- a/internal/cmd/propose.go
+++ b/internal/cmd/propose.go
@@ -265,8 +265,8 @@ func determineProposeData(repo execute.OpenRepoResult, args proposeArgs) (data p
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	validatedConfig, exit, err := validate.Config(validate.ConfigArgs{
 		Backend:            repo.Backend,
 		BranchInfos:        branchesSnapshot.Branches,
diff --git a/internal/cmd/rename.go b/internal/cmd/rename.go
index 5eb43a051..14925fbb7 100644
--- a/internal/cmd/rename.go
+++ b/internal/cmd/rename.go
@@ -219,8 +219,8 @@ func determineRenameData(args []string, force configdomain.Force, repo execute.O
 	if !hasOldBranch {
 		return data, configdomain.ProgramFlowExit, fmt.Errorf(messages.BranchDoesntExist, oldBranchName)
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/set_parent.go b/internal/cmd/set_parent.go
index bf783d16d..23376880b 100644
--- a/internal/cmd/set_parent.go
+++ b/internal/cmd/set_parent.go
@@ -137,7 +137,7 @@ Start:
 			entries := dialog.NewSwitchBranchEntries(dialog.NewSwitchBranchEntriesArgs{
 				BranchInfos:       data.branchesSnapshot.Branches,
 				BranchTypes:       []configdomain.BranchType{},
-				BranchesAndTypes:  repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(data.branchesSnapshot.Branches.Names()),
+				BranchesAndTypes:  repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(data.branchesSnapshot.Branches.NamesLocalBranches()),
 				ExcludeBranches:   excludeBranches,
 				Lineage:           repo.UnvalidatedConfig.NormalConfig.Lineage,
 				MainBranch:        repo.UnvalidatedConfig.UnvalidatedConfig.MainBranch,
@@ -280,8 +280,8 @@ func determineSetParentData(repo execute.OpenRepoResult) (data setParentData, fl
 	if branchesSnapshot.DetachedHead {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.SetParentRepoHasDetachedHead)
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/ship/shared.go b/internal/cmd/ship/shared.go
index f4d20a929..a789dbc70 100644
--- a/internal/cmd/ship/shared.go
+++ b/internal/cmd/ship/shared.go
@@ -112,8 +112,8 @@ func determineSharedShipData(args []string, repo execute.OpenRepoResult, shipStr
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
 	}
 	isShippingInitialBranch := branchToShip == initialBranch
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/skip.go b/internal/cmd/skip.go
index ac703bf7a..42fc1630b 100644
--- a/internal/cmd/skip.go
+++ b/internal/cmd/skip.go
@@ -125,8 +125,8 @@ Start:
 			activeBranch = currentBranch
 		}
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return err
diff --git a/internal/cmd/swap/cmd.go b/internal/cmd/swap/cmd.go
index a8a4fde4e..93df05212 100644
--- a/internal/cmd/swap/cmd.go
+++ b/internal/cmd/swap/cmd.go
@@ -250,8 +250,8 @@ func determineSwapData(repo execute.OpenRepoResult) (data swapData, flow configd
 	if currentBranchInfo.SyncStatus == gitdomain.SyncStatusOtherWorktree {
 		return data, configdomain.ProgramFlowExit, fmt.Errorf(messages.BranchOtherWorktree, currentBranch)
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/switch.go b/internal/cmd/switch.go
index 020e83009..53ecd0076 100644
--- a/internal/cmd/switch.go
+++ b/internal/cmd/switch.go
@@ -105,7 +105,7 @@ Start:
 	case configdomain.ProgramFlowRestart:
 		goto Start
 	}
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(data.branchesSnapshot.Branches.Names())
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(data.branchesSnapshot.Branches.NamesAllBranches())
 	unknownBranchType := repo.UnvalidatedConfig.NormalConfig.UnknownBranchType
 	entries := dialog.NewSwitchBranchEntries(dialog.NewSwitchBranchEntriesArgs{
 		BranchInfos:       data.branchesSnapshot.Branches,
diff --git a/internal/cmd/sync/cmd.go b/internal/cmd/sync/cmd.go
index 3f8376fe1..8d8497359 100644
--- a/internal/cmd/sync/cmd.go
+++ b/internal/cmd/sync/cmd.go
@@ -338,8 +338,8 @@ func determineSyncData(repo execute.OpenRepoResult, args determineSyncDataArgs)
 	if !hasInitialBranch {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
@@ -374,7 +374,7 @@ func determineSyncData(repo execute.OpenRepoResult, args determineSyncDataArgs)
 	default:
 		branchNamesToSync = gitdomain.LocalBranchNames{initialBranch}
 	}
-	branchesAndTypes = repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	branchesAndTypes = repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	validatedConfig, exit, err = validate.Config(validate.ConfigArgs{
 		Backend:            repo.Backend,
 		BranchInfos:        branchesSnapshot.Branches,
diff --git a/internal/cmd/undo.go b/internal/cmd/undo.go
index 0fa20557b..becfcedb9 100644
--- a/internal/cmd/undo.go
+++ b/internal/cmd/undo.go
@@ -161,8 +161,8 @@ func determineUndoData(repo execute.OpenRepoResult) (data undoData, flow configd
 	case configdomain.ProgramFlowExit, configdomain.ProgramFlowRestart:
 		return data, flow, nil
 	}
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/cmd/walk.go b/internal/cmd/walk.go
index f4bf5e290..7dae16c46 100644
--- a/internal/cmd/walk.go
+++ b/internal/cmd/walk.go
@@ -252,8 +252,8 @@ func determineWalkData(repo execute.OpenRepoResult, all configdomain.AllBranches
 	if !hasInitialBranch {
 		return data, configdomain.ProgramFlowExit, errors.New(messages.CurrentBranchCannotDetermine)
 	}
-	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().Names())
-	localBranches := branchesSnapshot.Branches.LocalBranches().Names()
+	branchesAndTypes := repo.UnvalidatedConfig.UnvalidatedBranchesAndTypes(branchesSnapshot.Branches.LocalBranches().NamesLocalBranches())
+	localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
 	remotes, err := repo.Git.Remotes(repo.Backend)
 	if err != nil {
 		return data, configdomain.ProgramFlowExit, err
diff --git a/internal/git/gitdomain/branch_info.go b/internal/git/gitdomain/branch_info.go
index fd6bb7072..f1d3b2263 100644
--- a/internal/git/gitdomain/branch_info.go
+++ b/internal/git/gitdomain/branch_info.go
@@ -41,6 +41,16 @@ func (self BranchInfo) GetLocalOrRemoteName() BranchName {
 	panic("BranchInfo has neither a local nor remote name")
 }
 
+func (self BranchInfo) GetLocalOrRemoteNameAsLocalName() LocalBranchName {
+	if localName, hasLocalName := self.LocalName.Get(); hasLocalName {
+		return localName
+	}
+	if remoteName, hasRemoteName := self.RemoteName.Get(); hasRemoteName {
+		return remoteName.LocalBranchName()
+	}
+	panic("BranchInfo has neither a local nor remote name")
+}
+
 func (self BranchInfo) GetLocalOrRemoteSHA() SHA {
 	if localSHA, has := self.LocalSHA.Get(); has {
 		return localSHA
diff --git a/internal/git/gitdomain/branch_infos.go b/internal/git/gitdomain/branch_infos.go
index 498c83e21..f6de24bbc 100644
--- a/internal/git/gitdomain/branch_infos.go
+++ b/internal/git/gitdomain/branch_infos.go
@@ -138,8 +138,17 @@ func (self BranchInfos) LocalBranchesWithDeletedTrackingBranches() BranchInfos {
 	return result
 }
 
-// Names provides the names of all local branches in this BranchesSyncStatus instance.
-func (self BranchInfos) Names() LocalBranchNames {
+// NamesAllBranches provides the local names for all branches in this BranchesSyncStatus instance.
+func (self BranchInfos) NamesAllBranches() LocalBranchNames {
+	result := make(LocalBranchNames, 0, len(self))
+	for _, bi := range self {
+		result = append(result, bi.GetLocalOrRemoteNameAsLocalName())
+	}
+	return result
+}
+
+// NamesLocalBranches provides the names of all local branches in this BranchesSyncStatus instance.
+func (self BranchInfos) NamesLocalBranches() LocalBranchNames {
 	result := make(LocalBranchNames, 0, len(self))
 	for _, bi := range self {
 		if localName, hasLocalName := bi.LocalName.Get(); hasLocalName {
diff --git a/internal/validate/handle_unfinished_state.go b/internal/validate/handle_unfinished_state.go
index 44f08e84c..67491bedf 100644
--- a/internal/validate/handle_unfinished_state.go
+++ b/internal/validate/handle_unfinished_state.go
@@ -153,7 +153,7 @@ func quickValidateConfig(args quickValidateConfigArgs) (config.ValidatedConfig,
 		if err != nil {
 			return config.EmptyValidatedConfig(), false, err
 		}
-		localBranches := branchesSnapshot.Branches.LocalBranches().Names()
+		localBranches := branchesSnapshot.Branches.LocalBranches().NamesLocalBranches()
 		var exit dialogdomain.Exit
 		_, mainBranch, exit, err = dialog.MainBranch(dialog.MainBranchArgs{
 			Inputs:         args.inputs,



Test patch:
diff --git a/internal/git/gitdomain/branch_info_test.go b/internal/git/gitdomain/branch_info_test.go
index 3e0e978c1..6a5b43ff3 100644
--- a/internal/git/gitdomain/branch_info_test.go
+++ b/internal/git/gitdomain/branch_info_test.go
@@ -42,6 +42,37 @@ func TestBranchInfo(t *testing.T) {
 		})
 	})
 
+	t.Run("GetLocalOrRemoteNameAsLocalName", func(t *testing.T) {
+		t.Parallel()
+		t.Run("has local and remote name", func(t *testing.T) {
+			t.Parallel()
+			branchInfo := gitdomain.BranchInfo{
+				LocalName:  gitdomain.NewLocalBranchNameOption("branch"),
+				RemoteName: gitdomain.NewRemoteBranchNameOption("origin/branch"),
+			}
+			have := branchInfo.GetLocalOrRemoteNameAsLocalName()
+			must.EqOp(t, "branch", have)
+		})
+		t.Run("has only local name", func(t *testing.T) {
+			t.Parallel()
+			branchInfo := gitdomain.BranchInfo{
+				LocalName:  gitdomain.NewLocalBranchNameOption("branch"),
+				RemoteName: None[gitdomain.RemoteBranchName](),
+			}
+			have := branchInfo.GetLocalOrRemoteNameAsLocalName()
+			must.EqOp(t, "branch", have)
+		})
+		t.Run("has only remote name", func(t *testing.T) {
+			t.Parallel()
+			branchInfo := gitdomain.BranchInfo{
+				LocalName:  None[gitdomain.LocalBranchName](),
+				RemoteName: gitdomain.NewRemoteBranchNameOption("origin/branch"),
+			}
+			have := branchInfo.GetLocalOrRemoteNameAsLocalName()
+			must.EqOp(t, "branch", have)
+		})
+	})
+
 	t.Run("GetLocalOrRemoteSHA", func(t *testing.T) {
 		t.Parallel()
 		t.Run("has local and remote SHA", func(t *testing.T) {
diff --git a/internal/git/gitdomain/branch_infos_test.go b/internal/git/gitdomain/branch_infos_test.go
index dc5699a92..77d0ab353 100644
--- a/internal/git/gitdomain/branch_infos_test.go
+++ b/internal/git/gitdomain/branch_infos_test.go
@@ -323,7 +323,7 @@ func TestBranchInfos(t *testing.T) {
 				RemoteSHA:  None[gitdomain.SHA](),
 			},
 		}
-		have := bs.LocalBranches().Names()
+		have := bs.LocalBranches().NamesLocalBranches()
 		want := gitdomain.NewLocalBranchNames("up-to-date", "ahead", "behind", "local-only", "deleted-at-remote")
 		must.Eq(t, want, have)
 	})
@@ -374,7 +374,7 @@ func TestBranchInfos(t *testing.T) {
 				RemoteSHA:  None[gitdomain.SHA](),
 			},
 		}
-		have := bs.LocalBranchesWithDeletedTrackingBranches().Names()
+		have := bs.LocalBranchesWithDeletedTrackingBranches().NamesLocalBranches()
 		want := gitdomain.NewLocalBranchNames("deleted-at-remote")
 		must.Eq(t, want, have)
 	})
@@ -413,7 +413,7 @@ func TestBranchInfos(t *testing.T) {
 		})
 	})
 
-	t.Run("Names", func(t *testing.T) {
+	t.Run("NamesAllBranches", func(t *testing.T) {
 		t.Parallel()
 		bs := gitdomain.BranchInfos{
 			gitdomain.BranchInfo{
@@ -438,7 +438,37 @@ func TestBranchInfos(t *testing.T) {
 				RemoteSHA:  Some(gitdomain.NewSHA("111111")),
 			},
 		}
-		have := bs.Names()
+		have := bs.NamesAllBranches()
+		want := gitdomain.NewLocalBranchNames("one", "two", "three")
+		must.Eq(t, want, have)
+	})
+
+	t.Run("NamesLocalBranches", func(t *testing.T) {
+		t.Parallel()
+		bs := gitdomain.BranchInfos{
+			gitdomain.BranchInfo{
+				LocalName:  gitdomain.NewLocalBranchNameOption("one"),
+				LocalSHA:   Some(gitdomain.NewSHA("111111")),
+				SyncStatus: gitdomain.SyncStatusLocalOnly,
+				RemoteName: None[gitdomain.RemoteBranchName](),
+				RemoteSHA:  None[gitdomain.SHA](),
+			},
+			gitdomain.BranchInfo{
+				LocalName:  gitdomain.NewLocalBranchNameOption("two"),
+				LocalSHA:   Some(gitdomain.NewSHA("111111")),
+				SyncStatus: gitdomain.SyncStatusLocalOnly,
+				RemoteName: None[gitdomain.RemoteBranchName](),
+				RemoteSHA:  None[gitdomain.SHA](),
+			},
+			gitdomain.BranchInfo{
+				LocalName:  None[gitdomain.LocalBranchName](),
+				LocalSHA:   None[gitdomain.SHA](),
+				SyncStatus: gitdomain.SyncStatusRemoteOnly,
+				RemoteName: Some(gitdomain.NewRemoteBranchName("origin/three")),
+				RemoteSHA:  Some(gitdomain.NewSHA("111111")),
+			},
+		}
+		have := bs.NamesLocalBranches()
 		want := gitdomain.NewLocalBranchNames("one", "two")
 		must.Eq(t, want, have)
 	})