@@ -269,6 +269,19 @@ func createNewBranchWorktree(gitClient git.GitClient, branchName, baseBranch, wo
269269
270270 // Create worktree with new branch
271271 if err := gitClient .AddWorktreeNewBranch (worktreePath , branchName , baseRef ); err != nil {
272+ if existingPath := parseWorktreeInUseError (err ); existingPath != "" {
273+ return fmt .Errorf ("branch %s is already checked out in another worktree\n \n " +
274+ "Existing worktree: %s\n \n " +
275+ "Options:\n " +
276+ " 1. Navigate to existing worktree:\n " +
277+ " %s\n \n " +
278+ " 2. Remove existing worktree and retry:\n " +
279+ " %s" ,
280+ ui .Branch (branchName ),
281+ existingPath ,
282+ ui .Command (fmt .Sprintf ("cd %s" , existingPath )),
283+ ui .Command (fmt .Sprintf ("git worktree remove %s" , existingPath )))
284+ }
272285 return fmt .Errorf ("failed to create worktree: %w" , err )
273286 }
274287
@@ -293,6 +306,19 @@ func createWorktreeForExisting(gitClient git.GitClient, branchName, worktreePath
293306 if gitClient .BranchExists (branchName ) {
294307 fmt .Printf ("Creating worktree for local branch %s\n " , ui .Branch (branchName ))
295308 if err := gitClient .AddWorktree (worktreePath , branchName ); err != nil {
309+ if existingPath := parseWorktreeInUseError (err ); existingPath != "" {
310+ return fmt .Errorf ("branch %s is already checked out in another worktree\n \n " +
311+ "Existing worktree: %s\n \n " +
312+ "Options:\n " +
313+ " 1. Navigate to existing worktree:\n " +
314+ " %s\n \n " +
315+ " 2. Remove existing worktree and retry:\n " +
316+ " %s" ,
317+ ui .Branch (branchName ),
318+ existingPath ,
319+ ui .Command (fmt .Sprintf ("cd %s" , existingPath )),
320+ ui .Command (fmt .Sprintf ("git worktree remove %s" , existingPath )))
321+ }
296322 return fmt .Errorf ("failed to create worktree: %w" , err )
297323 }
298324 if ! dryRun {
@@ -493,8 +519,7 @@ func getWorktreesBaseDir(gitClient git.GitClient) (string, error) {
493519 }
494520
495521 expanded := os .ExpandEnv (configured )
496- if strings .HasPrefix (expanded , "~" ) {
497- trimmed := strings .TrimPrefix (expanded , "~" )
522+ if trimmed , found := strings .CutPrefix (expanded , "~" ); found {
498523 trimmed = strings .TrimPrefix (trimmed , string (os .PathSeparator ))
499524 expanded = filepath .Join (homeDir , trimmed )
500525 }
@@ -542,3 +567,24 @@ func symlinkEnvFile(gitClient git.GitClient, worktreePath string) {
542567
543568 fmt .Println (ui .Success ("Symlinked .env file" ))
544569}
570+
571+ // parseWorktreeInUseError extracts the existing worktree path from a git error.
572+ // Returns the path if error matches "is already used by worktree at", empty string otherwise.
573+ func parseWorktreeInUseError (err error ) string {
574+ if err == nil {
575+ return ""
576+ }
577+ errStr := err .Error ()
578+ // Git error format: fatal: 'branch' is already used by worktree at 'path'
579+ marker := "is already used by worktree at '"
580+ idx := strings .Index (errStr , marker )
581+ if idx == - 1 {
582+ return ""
583+ }
584+ pathStart := idx + len (marker )
585+ pathEnd := strings .LastIndex (errStr , "'" )
586+ if pathEnd <= pathStart {
587+ return ""
588+ }
589+ return errStr [pathStart :pathEnd ]
590+ }
0 commit comments