Skip to content

git_ui: Improve the staged & unstaged grouping in the git panel - #60976

Merged
danilo-leal merged 10 commits into
mainfrom
staging-grouping-adjustments
Jul 14, 2026
Merged

git_ui: Improve the staged & unstaged grouping in the git panel#60976
danilo-leal merged 10 commits into
mainfrom
staging-grouping-adjustments

Conversation

@danilo-leal

@danilo-leal danilo-leal commented Jul 14, 2026

Copy link
Copy Markdown
Member

Follow up to #59884

This PR refines how the git panel behaves when grouping changes by staging state, with a focus on making staging workflows predictable and conflict resolution safe.

  • Renamed the "Group By" menu options to describe what you actually see: "Tracked & Untracked" (was "Status") and "Staged & Unstaged" (was "Staging").
  • When grouping by staged & unstaged, both sections now stay visible even when empty, showing a placeholder message ("No staged changes yet" / "No unstaged changes"). Previously an empty section disappeared entirely, which made the panel layout jump around as you staged and unstaged files, and made it harder to tell at a glance that nothing was staged yet.
  • Section header controls are now consistent checkboxes everywhere (previously a mix of checkboxes and +/− icon buttons), with "Stage All" / "Unstage All" tooltips. Headers of empty sections render no checkbox and don't react to clicks or hover. I appreciate the debate that happened in the PR linked above about this but I was personally having a hard time understanding what was the difference in interaction given the action was exactly the same, we were just having different UIs, which looked inconsistent.
  • Arrow-key navigation now skips over section headers and empty-section placeholder rows in both flat and tree view, instead of getting stuck or selecting non-interactive rows — including when jumping to the first or last entry.
  • In the staged & unstaged grouping, a partially staged file appears in both sections. Each row's checkbox and tooltip now follow the section it's rendered in: rows in Staged always unstage, rows in Unstaged always stage — including via shift-click range operations, which now also support bulk unstaging within the Staged section (previously ranges could only stage). The context menu's Stage/Unstage label follows the same rule and stays in sync with in-flight staging operations.
  • Conflicted files are grouped by whether the current merge marked them conflicted (rather than raw status), so a conflict you've resolved stays visible under "Conflicts" until the merge concludes. On top of that, resolution is now one-way in the UI:
    • Ticking a conflicted file's checkbox marks it resolved (stages it). Once resolved, the checkbox is disabled with a "Conflict marked as resolved" tooltip — unticking it would silently discard git's record of the unmerged base/ours/theirs versions, a round-trip git can't actually perform.
    • The same lock applies everywhere the file can be reached: the keyboard toggle, folder checkboxes in tree view, the Conflicts section header (disabled once all conflicts are resolved), "Stage All"/"Unstage All" on the Staged/Unstaged headers, and shift-click range sweeps — none of them will resolve or un-resolve a conflict as a side effect.
    • The explicit git: unstage file action still works as a deliberate escape hatch.

Here's a video, where you can see I stage and unstage whole files, make a partial staging, and get into a merge-conflict state, where the conflicted files are tagged as resolved:

Screenshot.2026-07-14.at.11.11.mp4

Release Notes:

  • N/A (given the feature hasn't been released yet)

@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Jul 14, 2026
@zed-community-bot zed-community-bot Bot added the staff Pull requests authored by a current member of Zed staff label Jul 14, 2026

@ChristopherBiscardi ChristopherBiscardi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome

@ChristopherBiscardi
ChristopherBiscardi added this pull request to the merge queue Jul 14, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 14, 2026
@danilo-leal
danilo-leal added this pull request to the merge queue Jul 14, 2026
Merged via the queue into main with commit 48a0cbc Jul 14, 2026
36 checks passed
@danilo-leal
danilo-leal deleted the staging-grouping-adjustments branch July 14, 2026 18:09
@chirivelli

Copy link
Copy Markdown
Collaborator
  • Section header controls are now consistent checkboxes everywhere (previously a mix of checkboxes and +/− icon buttons), with "Stage All" / "Unstage All" tooltips. Headers of empty sections render no checkbox and don't react to clicks or hover. I appreciate the debate that happened in the PR linked above about this but I was personally having a hard time understanding what was the difference in interaction given the action was exactly the same, we were just having different UIs, which looked inconsistent.

@danilo-leal
I urge you to reconsider.

  • Its a common UI/UX followed in other editors
  • "Group by none" and "Group by status" didn't used to move files around so checkbox was fine there
  • Checkbox will be moving stuff around now (should be button like +/-)
  • rest of the changes were great.

As this is not out yet, I am hesitant to make an issue for this.

@danilo-leal

Copy link
Copy Markdown
Member Author

@chirivelli What I was confused about the +/- thing was that despite the icon we show, the interaction was exactly the same, no? You click on the checkbox/button and the file gets staged and moved to the staged section. Even in partial staging scenarios, the +/- icon buttons didn't do a better/more special job of communicating that... so, to me it just felt like inconsistent UI treatment, given that the main difference between "tracked/untracked" and "staged/unstaged" is that in the former case, files never leave their bucket despite staging status, and in the latter, they do, by definition.

@chirivelli

Copy link
Copy Markdown
Collaborator

Agreed, the interaction is exactly the same.

But for partially staged files checkboxes showing ticked and empty in both sections is confusing (why is the checkbox checked when the file is not completely staged?).

The +/- icon buttons doesn't indicate their state, just indicates the action (I'm considering them as neutral).
Now as this new "Grouping" option move files around the bucket they are in is the state. So no need of checkbox, but we do need buttons for the actions.

@danilo-leal

Copy link
Copy Markdown
Member Author

But for partially staged files checkboxes showing ticked and empty in both sections is confusing (why is the checkbox checked when the file is not completely staged?).

I hear that, but I am not sure if having the +/- icon buttons solve this in a dramatically better way, because you'd be still seeing an entry for the same file twice in each bucket, but instead of one with a check and another with no check, one with a plus and another with a minus... Like, it's sort of a similar level of clarity when it comes to communicating its partiality.

jolutz pushed a commit to jolutz/zed that referenced this pull request Aug 8, 2026
…industries#60976)

Follow up to zed-industries#59884

This PR refines how the git panel behaves when grouping changes by
staging state, with a focus on making staging workflows predictable and
conflict resolution safe.

- Renamed the "Group By" menu options to describe what you actually see:
**"Tracked & Untracked"** (was "Status") and **"Staged & Unstaged"**
(was "Staging").
- When grouping by staged & unstaged, both sections now stay visible
even when empty, showing a placeholder message ("No staged changes yet"
/ "No unstaged changes"). Previously an empty section disappeared
entirely, which made the panel layout jump around as you staged and
unstaged files, and made it harder to tell at a glance that nothing was
staged yet.
- Section header controls are now consistent checkboxes everywhere
(previously a mix of checkboxes and +/− icon buttons), with "Stage All"
/ "Unstage All" tooltips. Headers of empty sections render no checkbox
and don't react to clicks or hover. I appreciate the debate that
happened in the PR linked above about this but I was personally having a
hard time understanding what was the difference in interaction given the
action was exactly the same, we were just having different UIs, which
looked inconsistent.
- Arrow-key navigation now skips over section headers and empty-section
placeholder rows in both flat and tree view, instead of getting stuck or
selecting non-interactive rows — including when jumping to the first or
last entry.
- In the staged & unstaged grouping, a partially staged file appears in
both sections. Each row's checkbox and tooltip now follow the section
it's rendered in: rows in Staged always unstage, rows in Unstaged always
stage — including via shift-click range operations, which now also
support bulk *unstaging* within the Staged section (previously ranges
could only stage). The context menu's Stage/Unstage label follows the
same rule and stays in sync with in-flight staging operations.
- Conflicted files are grouped by whether the current merge marked them
conflicted (rather than raw status), so a conflict you've resolved stays
visible under "Conflicts" until the merge concludes. On top of that,
resolution is now one-way in the UI:
- Ticking a conflicted file's checkbox marks it resolved (stages it).
Once resolved, the checkbox is disabled with a "Conflict marked as
resolved" tooltip — unticking it would silently discard git's record of
the unmerged base/ours/theirs versions, a round-trip git can't actually
perform.
- The same lock applies everywhere the file can be reached: the keyboard
toggle, folder checkboxes in tree view, the Conflicts section header
(disabled once all conflicts are resolved), "Stage All"/"Unstage All" on
the Staged/Unstaged headers, and shift-click range sweeps — none of them
will resolve or un-resolve a conflict as a side effect.
- The explicit `git: unstage file` action still works as a deliberate
escape hatch.

---

Here's a video, where you can see I stage and unstage whole files, make
a partial staging, and get into a merge-conflict state, where the
conflicted files are tagged as resolved:


https://github.com/user-attachments/assets/d27ef9c6-5691-45c1-91ab-c3b152aaaa60

---

Release Notes:

- N/A _(given the feature hasn't been released yet_)
playdohface pushed a commit to playdohface/zed that referenced this pull request Aug 29, 2026
…industries#60976)

Follow up to zed-industries#59884

This PR refines how the git panel behaves when grouping changes by
staging state, with a focus on making staging workflows predictable and
conflict resolution safe.

- Renamed the "Group By" menu options to describe what you actually see:
**"Tracked & Untracked"** (was "Status") and **"Staged & Unstaged"**
(was "Staging").
- When grouping by staged & unstaged, both sections now stay visible
even when empty, showing a placeholder message ("No staged changes yet"
/ "No unstaged changes"). Previously an empty section disappeared
entirely, which made the panel layout jump around as you staged and
unstaged files, and made it harder to tell at a glance that nothing was
staged yet.
- Section header controls are now consistent checkboxes everywhere
(previously a mix of checkboxes and +/− icon buttons), with "Stage All"
/ "Unstage All" tooltips. Headers of empty sections render no checkbox
and don't react to clicks or hover. I appreciate the debate that
happened in the PR linked above about this but I was personally having a
hard time understanding what was the difference in interaction given the
action was exactly the same, we were just having different UIs, which
looked inconsistent.
- Arrow-key navigation now skips over section headers and empty-section
placeholder rows in both flat and tree view, instead of getting stuck or
selecting non-interactive rows — including when jumping to the first or
last entry.
- In the staged & unstaged grouping, a partially staged file appears in
both sections. Each row's checkbox and tooltip now follow the section
it's rendered in: rows in Staged always unstage, rows in Unstaged always
stage — including via shift-click range operations, which now also
support bulk *unstaging* within the Staged section (previously ranges
could only stage). The context menu's Stage/Unstage label follows the
same rule and stays in sync with in-flight staging operations.
- Conflicted files are grouped by whether the current merge marked them
conflicted (rather than raw status), so a conflict you've resolved stays
visible under "Conflicts" until the merge concludes. On top of that,
resolution is now one-way in the UI:
- Ticking a conflicted file's checkbox marks it resolved (stages it).
Once resolved, the checkbox is disabled with a "Conflict marked as
resolved" tooltip — unticking it would silently discard git's record of
the unmerged base/ours/theirs versions, a round-trip git can't actually
perform.
- The same lock applies everywhere the file can be reached: the keyboard
toggle, folder checkboxes in tree view, the Conflicts section header
(disabled once all conflicts are resolved), "Stage All"/"Unstage All" on
the Staged/Unstaged headers, and shift-click range sweeps — none of them
will resolve or un-resolve a conflict as a side effect.
- The explicit `git: unstage file` action still works as a deliberate
escape hatch.

---

Here's a video, where you can see I stage and unstage whole files, make
a partial staging, and get into a merge-conflict state, where the
conflicted files are tagged as resolved:


https://github.com/user-attachments/assets/d27ef9c6-5691-45c1-91ab-c3b152aaaa60

---

Release Notes:

- N/A _(given the feature hasn't been released yet_)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement staff Pull requests authored by a current member of Zed staff

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants