Skip to content

Make creating worktrees simpler and less error-prone#5741

Merged
stefanhaller merged 7 commits into
masterfrom
worktree-creation-ux
Jul 3, 2026
Merged

Make creating worktrees simpler and less error-prone#5741
stefanhaller merged 7 commits into
masterfrom
worktree-creation-ux

Conversation

@stefanhaller

Copy link
Copy Markdown
Collaborator

Creating a worktree in lazygit used to be more awkward than it needed to be:

  • The first thing you were asked was whether you wanted a "normal" or "detached" worktree — a distinction that's confusing to face up front, and meaningless when you're creating a worktree from a commit, tag or stash (both choices did the same thing there).
  • You then had to type the new worktree's path by hand. That's easy to get wrong (a mistyped .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.
  • If you picked a branch that was already checked out in another worktree, lazygit still asked you for a path and only told you it wouldn't work afterwards.
  • There was no quick way to create a new branch and a worktree for it (sharing the same name) in one step.

This PR reworks the whole flow:

  • No more up-front mode menu. Pressing w on 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'".
  • You never type a path from scratch. Lazygit offers ready-made locations — the folders your existing worktrees already live in, plus an optional configured default — and shows each as a full path before anything happens. The folder name is filled in for you from the branch (or the name you choose). You can still pick "Other…" to type a custom path.
  • Create a branch and its worktree in one step, with a single name used for both. Slashes are preserved, so feature/foo gives you a feature/foo branch and a matching nested folder.
  • Branches already checked out elsewhere are caught up front: the relevant option is greyed out with an explanation of why, instead of letting you do the work and then failing.
  • The worktrees panel's n is 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.defaultPath setting 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

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>
@stefanhaller stefanhaller force-pushed the worktree-creation-ux branch from 492483a to 4737b7e Compare July 3, 2026 16:52
stefanhaller and others added 6 commits July 3, 2026 18:53
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>
@stefanhaller stefanhaller force-pushed the worktree-creation-ux branch from 4737b7e to 7a67cea Compare July 3, 2026 16:53
@stefanhaller stefanhaller enabled auto-merge July 3, 2026 16:53
@stefanhaller stefanhaller merged commit 7458275 into master Jul 3, 2026
23 of 24 checks passed
@stefanhaller stefanhaller deleted the worktree-creation-ux branch July 3, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Suggest a path when creating worktrees Worktree path does not expand deafult path for worktrees

1 participant