Make creating worktrees simpler and less error-prone#5741
Merged
Conversation
This was referenced Jun 30, 2026
6bf788f to
492483a
Compare
The redesigned worktree-creation flow never asks the user to type a path from scratch; instead it offers candidate parent directories. Until a repo has any linked worktrees to learn from, there's nothing to offer, so let users seed that list with a configured default location. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
492483a to
4737b7e
Compare
This is the core of "never type a path from scratch": from the repo root, the configured default path, and the parents of existing worktrees, derive the ordered list of directories under which a new worktree could be placed. Pure and unit-tested here; wired into the creation flow in a later commit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The old flow forced an up-front "normal vs detached" menu (meaningless for commits, tags and stashes), then asked the user to type a worktree path from scratch — easy to get wrong, and ambiguous about what relative paths resolve against. It also offered the same two actions everywhere regardless of what was selected. Replace it with per-context "Worktree" menus whose items imply the intent (new branch + worktree, worktree for an existing branch, detached worktree), each feeding a shared name -> location -> create pipeline. The location menu offers candidate parent directories as absolute paths instead of a blank field, and "Worktree for a branch" is disabled (with a reason) when that branch is already checked out somewhere, rather than failing after the fact. Each ref/commit panel binds 'w' in its own controller and calls the matching typed entry point on the worktree helper, so which menu opens is decided statically by the call site rather than by dispatching on a ref's dynamic type. The three commit panels share one menu through BasicCommitsController; there is no longer a shared worktree-options controller. The worktrees-panel 'n' flow and its old core (NewWorktree / NewWorktreeCheckout) are left untouched here so nothing is written and then rewritten; they migrate, and the dead i18n strings get removed, in a follow-up commit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The old 'n' flow opened a "normal vs detached" menu (the same meaningless gate the 'w' flow used to have), then asked for a base ref, a path typed from scratch, and a branch name in three separate prompts. Replace it with a single picker prompt titled "New worktree for branch", suggesting local branches not already checked out anywhere, plus remote branches that don't yet have a local branch of the same name. The entered value is classified on confirm: an existing local branch checks out into a new worktree, a remote branch creates a new local tracking branch, and anything else creates a new branch off the current ref. All three then feed the same location menu the 'w' flow uses, so paths are chosen from candidates rather than typed blind. Picking a remote or new branch needs no separate name prompt — the picker value already is the name. Checked-out branches are filtered from the suggestions, and a verbatim type-in of one is rejected with an error. createWorktree now takes the context to switch focus to once the worktree is created, so 'n' lands back in the worktrees panel while 'w' still lands in the branches panel. This deletes the old NewWorktree / NewWorktreeCheckout core and the now- orphaned i18n (CreateWorktreeFrom, CreateWorktreeFromDetached, NewWorktreeBase, NewBranchNameLeaveBlank), completing the migration started for 'w'. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
RenameYamlKey can only rename a key in place, under the same parent. To migrate a keybinding from one section to another we need to relocate the key to a different parent mapping, which is a move, not a rename. MoveYamlKey creates intermediate maps at the destination as needed and prunes any maps left empty behind the key, so a section that held only the moved key doesn't linger as an empty mapping in the user's config. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The command was renamed from "View worktree options" to "New worktree", but its keybinding config key was still 'worktrees.viewWorktreeOptions'. That name no longer matches the command, and the 'worktrees' section made little sense: it held a single binding that isn't even used in the worktrees panel (that panel uses universal.new), only in the branches, remotes, tags, commits, and stash panels. Other keybinding sections are named after the panel they're local to; this one wasn't local to any. Move it to universal.newWorktree, which describes the action and drops the spurious section, and migrate existing configs automatically. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lazygit runs git directly rather than through a shell, so a literal "~" reaches `git worktree add` unexpanded and git creates a directory named "~" instead of using the home directory. Expand the tilde ourselves, both for paths typed into the "Other" location prompt and for the worktree.defaultPath config value. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4737b7e to
7a67cea
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Creating a worktree in lazygit used to be more awkward than it needed to be:
.worktrees, for instance), it wasn't clear whether you were meant to enter the parent folder or the full path, and it was ambiguous what a relative path would resolve against — especially when you were already inside another worktree.This PR reworks the whole flow:
won a branch, commit, tag, stash or remote branch opens a menu whose options are tailored to what you selected, and each option spells out exactly what it will do — e.g. "New worktree for 'main'", or "New detached worktree at 'v1.2.0'".feature/foogives you afeature/foobranch and a matching nested folder.nis now a single branch picker. Start typing, or pick from the list: choosing an existing branch checks it out in a new worktree, choosing a remote branch creates a local tracking branch for it, and typing a new name creates a new branch off your current one — each then simply asks where to put the worktree. Branches that are already checked out are left out of the suggestions.There's also a new
worktree.defaultPathsetting to tell lazygit where to create worktrees by default — useful before you have any existing worktrees for it to take its cue from. Starting that path with~/is supported (your home dir); this is also supported in the "Other…" path prompt mentioned above.Fixes #3230
Fixes #4708
Fixes #5664