Changes tree view + interactive rebase that actually works: GitWand v2.23
@gitwand/desktop@2.23.0 is a quality-of-life release for the two places you spend the most time: the Changes sidebar and the rebase editor. The sidebar learns to show your working-tree changes as a folder tree and to act on files and folders in place; interactive rebase gets a fix that makes it work in the shipped app, not just from source.
Most of this came in from @t1gu1's pull requests — reviewed, tested, and merged for this release.
See your changes as a folder tree
A flat list is fine for three changed files. For thirty, spread across a dozen directories, it's a wall. v2.23 adds a list / tree toggle to the Changes view, sitting in the controls row to the right of the monorepo scope picker (and stretching full-width with text labels when there's no scope picker to share the row with).
In tree mode, each git section — Staged, Modified, Untracked — nests its files under their folders, and the folders collapse and expand just like the sections themselves. Open the directories you're working in, fold the rest away. Selecting a file automatically expands the folders leading to it, so the tree never hides what you just clicked.
Both the chosen layout and the per-section collapse state are persisted in localStorage, so the sidebar comes back the way you left it.
The tree-building itself lives in a new useFileTree composable — a pure function that takes the flat list of changed entries and returns a nested structure, with a flatten step that projects it into render-ready rows respecting the collapsed state (the same approach the diff folder-tree already used). Keeping it pure means it's covered by unit tests rather than tangled into the component, including the fiddly cases: untracked directories that arrive as a single trailing-slash entry, cumulative folder paths used as stable keys, and roll-up counts per folder.
Stage, unstage, and discard — right where you are
The other half of the release is about acting on changes without drilling into section-level controls.
Every file row now carries a discard button alongside stage / unstage — previously discard lived only at the section header. In tree mode, folder rows get the same trio (stage / unstage / discard) operating on every file underneath them, so you can stage a whole directory or throw away a subtree in one click.
Section headers, folder rows, and file rows now share one visual vocabulary: a segmented "action group" — square buttons fused into a single pill, split by a hairline divider. And they're always visible now, not revealed on hover, so the action you want is never one mouse-position away from disappearing.
Interactive rebase that works in the packaged app
Here's the one that was quietly broken. Reordering, squashing, editing, or dropping commits from the rebase editor did nothing in the built desktop app — even though it worked perfectly when running GitWand from source.
The cause was a runtime gap. The frontend was POSTing the rebase to an /api/git-interactive-rebase HTTP endpoint that only exists in dev:web mode (the Node dev-server used during development). In the packaged Tauri app there's no such server, so the request went nowhere — the rebase silently never reached git.
v2.23 closes the gap with a real git_interactive_rebase Tauri command. It writes your edited todo list to a temp file and injects it into git rebase -i through GIT_SEQUENCE_EDITOR — the one piece of environment control a plain command runner can't provide — then reports back whether the rebase paused on a conflict, so the editor's continue / skip / abort flow works exactly as before. The Rust command, its backend.ts wrapper, and the dev-server route are all kept in parity, so the feature now behaves identically whether you're in the real app or dev:web.
While we were in there, every base-branch picker in the app — the branch menu, the merge picker, the rebase target — now shares a single branchSort: current branch first, then main / master, then most-recently-committed, then alphabetical. The branch you're most likely to be reaching for sits at the top, everywhere.
A note from the release: adding a new always-visible field to the branch selector nudged the main JS bundle five kilobytes over its budget. Rather than raise the ceiling, we lazy-loaded the create-branch field and the 600-line merge-preview panel with
defineAsyncComponent— they only mount inside pop-over and modal UI anyway — which split them into their own chunks and brought the main bundle back under budget. The bundle-size check that caught it runs in CI on every build.
Also in this release
- Linux AppImage external links — clicking the GitHub / Azure sign-in buttons, a PR or issue link in the Launchpad, "open repo on the web", or the changelog link did nothing in the released AppImage. The opener now tries
xdg-open,gio,kde-open5, and$BROWSERin turn with a de-polluted environment and surfaces a real error if they all fail, and every external link in the app routes through the OS opener — so none can silently do nothing again.
Upgrading
Desktop auto-update will offer v2.23.0, or grab it from GitHub Releases. @gitwand/core, @gitwand/cli, and @gitwand/mcp are on npm at 2.23.0. Nothing to migrate — everything here is additive, and your layout and folder-collapse preferences start fresh on first open.