Skip to content

git_ui: Add multi-select to git panel for bulk stage, unstage, and discard#60340

Open
justinschmitz97 wants to merge 2 commits into
zed-industries:mainfrom
justinschmitz97:git-panel-multi-select
Open

git_ui: Add multi-select to git panel for bulk stage, unstage, and discard#60340
justinschmitz97 wants to merge 2 commits into
zed-industries:mainfrom
justinschmitz97:git-panel-multi-select

Conversation

@justinschmitz97

@justinschmitz97 justinschmitz97 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Closes #26430
Complements: #52935 by Jacob Binnie

Enables multi-select in the Git Panel, following the Project Panel rules.

diff-bulk.mp4

Core selection gestures:

  1. Click one file, shift+click a file deeper in the list: all files between highlight.
  2. Click one file, then ctrl/cmd+click another file: it joins the selection; or removes it when selected.
  3. Shift+down extends the selection from the current row; shift+up shrinks it back and re-extends past the anchor.
  4. Escape with a selection clears it and keeps focus; Escape again toggles focus as before.
  5. Plain click collapses selection to file and opens its diff; double-click triggers the alternate open action.
  6. Shift+click on a checkbox still performs the pre-existing range staging.

Bulk operation gestures:

  1. Select multiple files, press space: if any member is unstaged, all become staged; press space again: all unstaged.
  2. Right-click a file inside the selection: menu reads Stage/Discard/Trash N files, depending on context.
  3. Select multiple files, press delete: confirmation prompt. Mixed selections: untracked = trashed, staged = unstaged.

Folders, in tree view:

  1. Ctrl/cmd+click a folder row behaves like its checkbox does: selects it as a unit, expands operations to descendants.
  2. Folder rows inside a shift range join the selection. A collapsed folder is selected including its hidden files.
  3. The same directory under Tracked and Untracked is two independent selections (so marks are section-qualified).
  4. Plain click on a folder still expands/collapses it and clears the selection.

Implementation notes:

  1. Selection is stored as repo paths plus section-qualified tree keys to survive status refreshes.*
  2. Stale entries are pruned on rebuild, selection is cleared on active repository change.
  3. Range selection follows visual order in both flat and tree view.
  4. Bulk operations batch into a single git operation.

* Not sure if this is the best option for storing it.

Why this is necessary

  • Multi-select has been an ongoing feature wish since 2025 with various upvotes
  • Current state of the art IDEs offer this (VSCode, IntelliJ, VS)
  • It greatly increases efficiency using the diff panel

Why is the PR from #52935 not enough?

This PR builds on its approach. Thanks to @jacobbinnie. But I noticed a few things:

  • never clears the selection when the active repository changes
  • a failed checkout or trash disappears silently
  • hardcodes single-click = project diff and double-click = file diff, ignoring the entry_primary_click_action setting
  • its context menu still reads "Stage File" / "Discard Changes" (singular)
  • discard prompt always says "Discard" even for an all-untracked selection that will actually trash files
  • no shift+arrow range extension, no Escape to clear
  • it skips directory rows entirely, in tree view you can't act on a folder's subtree at all
  • its range_select only ever accumulates, consecutive shift+clicks grow the set and nothing shrinks it
  • Uses Vec on marks, linear contains scans -> This PR uses HashSets, relevant for huge repos.
  • doesn't ship any tests -> This PR covers the whole range with tests too*

* Tests dominate this PR (~850 lines). The actual feature sits around 400.

@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Jul 3, 2026
@justinschmitz97 justinschmitz97 force-pushed the git-panel-multi-select branch from 51c9f8d to 0ba32ec Compare July 3, 2026 09:11
@smitbarmase smitbarmase added the area:integrations/git Git integration feedback label Jul 3, 2026
@justinschmitz97 justinschmitz97 force-pushed the git-panel-multi-select branch from 0ba32ec to 686345f Compare July 4, 2026 09:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:integrations/git Git integration feedback cla-signed The user has signed the Contributor License Agreement

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Multi-select files in the git panel

2 participants