Skip to content

git_ui: Add restore buttons to unstaged diff view - #60639

Merged
ChristopherBiscardi merged 5 commits into
zed-industries:mainfrom
npv12:npv12-unstaged-restore
Jul 12, 2026
Merged

git_ui: Add restore buttons to unstaged diff view#60639
ChristopherBiscardi merged 5 commits into
zed-industries:mainfrom
npv12:npv12-unstaged-restore

Conversation

@npv12

@npv12 npv12 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

The unstaged diff view introduced in the partially staged changes commit only had a Stage button but no Restore option. This adds:

  • A per-hunk Restore button in the inline hunk controls (disabled for new files)
  • A Restore button in the toolbar for selected hunks
  • A Restore All button in the toolbar to discard all unstaged changes
  • A restore method override on UnstagedDiffDelegate for the Restore action

Release Notes:

  • Added restore buttons to the unstaged diff view for discarding unstaged changes.

Objective

New unstaged and staged diffs were added in #46541 . However for unstaged changes, only option available is to stage a change. It would also be a common use case to restore the changes. (Like how it is done in uncommitted changes).

Solution

  • A per-hunk Restore button in the inline hunk controls (disabled for new files)
  • A Restore button in the toolbar for selected hunks
  • A Restore All button in the toolbar to discard all unstaged changes
  • A restore method override on UnstagedDiffDelegate for the Restore action

Testing

Tested in locally and ensured both features work

Self-Review Checklist:

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • The content adheres to Zed's UI standards (UX/UI and icon guidelines)
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Showcase

Screenshot 2026-07-09 at 9 00 47 AM

Note

I am still learning rust bit by bit. Please let me know if something is massively wrong. This is assisted by AI but reviewed by me with best of my knowledge.


Release Notes:

  • Added restore buttons to the unstaged diff view for discarding unstaged changes.

The unstaged diff view introduced in the partially staged changes commit
only had a Stage button but no Restore option. This adds:

- A per-hunk Restore button in the inline hunk controls (disabled for new files)
- A Restore button in the toolbar for selected hunks
- A Restore All button in the toolbar to discard all unstaged changes
- A restore method override on UnstagedDiffDelegate for the Restore action

Release Notes:

- Added restore buttons to the unstaged diff view for discarding unstaged changes.

Signed-off-by: Pranav <pranav10121@gmail.com>
@cla-bot cla-bot Bot added the cla-signed The user has signed the Contributor License Agreement label Jul 9, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 85ff4d428b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +685 to +688
let hunks: Vec<_> = snapshot
.diff_hunks()
.filter(|h| !h.is_created_file())
.collect();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wait for all diff buffers before restoring all

When the unstaged diff is still loading, this only restores hunks already present in the current multibuffer snapshot. DiffMultibuffer::refresh registers each loaded file as it arrives and doesn't mark the load task ready until after the whole loop, while this toolbar action is enabled as soon as the first restorable hunk is visible; in a repo with many or slow-to-open changed files, clicking “Restore All” during that window leaves later-loaded unstaged files unchanged despite the button claiming to restore all changes.

Useful? React with 👍 / 👎.

@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.

thanks! looks good on the "uncommitted changes" view, but the "Restore" button is missing in the staged changes view.

staged changes can be accessed via right-clicking the file in the git panel as seen here: image

"Restore all" is also missing in the staged changes view and the uncommitted changes view, as well as the split-button git panel dropdown

split button dropdown location image

@npv12

npv12 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

thanks! looks good on the "uncommitted changes" view, but the "Restore" button is missing in the staged changes view.
staged changes can be accessed via right-clicking the file in the git panel as seen here:

"Restore all" is also missing in the staged changes view and the uncommitted changes view, as well as the split-button git panel dropdown
split button dropdown location

i am not sure what restore would do in staged changes view? Will it unstage and remove the changes? That seems a bit excessive. For uncommitted changes, if a change is unstaged, we show two options (stage and restore) but we show only "unstage" option when a change is staged. Going with same semantics, Restore should not be part of staged changes

I will add restore all to the dropdown though.

@ChristopherBiscardi

Copy link
Copy Markdown
Contributor

i am not sure what restore would do in staged changes view?

Presumably the same thing it does in the uncommitted changes view on a staged hunk, which is already implemented in this PR.

image

@ChristopherBiscardi ChristopherBiscardi self-assigned this Jul 9, 2026
@npv12

npv12 commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

i am not sure what restore would do in staged changes view?

Presumably the same thing it does in the uncommitted changes view on a staged hunk, which is already implemented in this PR.

Hi @ChristopherBiscardi I looked into it and hit these blockers.

  1. Read-only editor: The staged diff view sets rhs_editor.set_read_only(true) (staged_diff.rs:299). The default restore impl in DiffHunkDelegate checks editor.read_only(cx) and returns early, so it never runs. I can override restore on StagedDiffDelegate to skip that check.
  2. Wrong buffer: The uncommitted view's multibuffer wraps the worktree buffer, so restore_diff_hunks edits the right thing. The staged view's multibuffer wraps the index buffer. When resolve_diff_hunks resolves hunks for the staged delegate, hunks.buffer points to the index buffer, not the worktree buffer. Restoring by editing the index buffer would just redo what unstage_staged_hunks already did optimistically. To actually restore the file content in the working tree, I'd need to look up the worktree buffer ID from the git store's buffer_ids_by_index_text_buffer_id mapping and edit that buffer instead. But I am not liking this approach either.

@dinocosta dinocosta added the area:integrations/git Git integration feedback label Jul 9, 2026
@ChristopherBiscardi

Copy link
Copy Markdown
Contributor

Thanks for looking into it. the current behavior is fine for this PR.

I ran cargo fmt for CI and kicked off the tests again

@npv12

npv12 commented Jul 11, 2026

Copy link
Copy Markdown
Contributor Author

Fixed the clippy warning from previous run

@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.

thanks!

@ChristopherBiscardi
ChristopherBiscardi added this pull request to the merge queue Jul 12, 2026
Merged via the queue into zed-industries:main with commit 60099a0 Jul 12, 2026
34 checks passed
@npv12
npv12 deleted the npv12-unstaged-restore branch July 12, 2026 13:56
jolutz pushed a commit to jolutz/zed that referenced this pull request Aug 8, 2026
The unstaged diff view introduced in the partially staged changes commit
only had a Stage button but no Restore option. This adds:

- A per-hunk Restore button in the inline hunk controls (disabled for
new files)
- A Restore button in the toolbar for selected hunks
- A Restore All button in the toolbar to discard all unstaged changes
- A restore method override on UnstagedDiffDelegate for the Restore
action

Release Notes:

- Added restore buttons to the unstaged diff view for discarding
unstaged changes.

# Objective
New unstaged and staged diffs were added in zed-industries#46541 . However for
unstaged changes, only option available is to stage a change. It would
also be a common use case to restore the changes. (Like how it is done
in uncommitted changes).

## Solution
- A per-hunk Restore button in the inline hunk controls (disabled for
new files)
- A Restore button in the toolbar for selected hunks
- A Restore All button in the toolbar to discard all unstaged changes
- A restore method override on UnstagedDiffDelegate for the Restore
action

## Testing
Tested in locally and ensured both features work

## Self-Review Checklist:

- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable

## Showcase
<img width="1141" height="635" alt="Screenshot 2026-07-09 at 9 00 47 AM"
src="https://github.com/user-attachments/assets/b1d3f091-9f1d-49c6-87e6-9efad25e62dd"
/>

## Note
I am still learning rust bit by bit. Please let me know if something is
massively wrong. This is assisted by AI but reviewed by me with best of
my knowledge.

---

Release Notes:

- Added restore buttons to the unstaged diff view for discarding
unstaged changes.

---------

Signed-off-by: Pranav <pranav10121@gmail.com>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
playdohface pushed a commit to playdohface/zed that referenced this pull request Aug 29, 2026
The unstaged diff view introduced in the partially staged changes commit
only had a Stage button but no Restore option. This adds:

- A per-hunk Restore button in the inline hunk controls (disabled for
new files)
- A Restore button in the toolbar for selected hunks
- A Restore All button in the toolbar to discard all unstaged changes
- A restore method override on UnstagedDiffDelegate for the Restore
action

Release Notes:

- Added restore buttons to the unstaged diff view for discarding
unstaged changes.

# Objective
New unstaged and staged diffs were added in zed-industries#46541 . However for
unstaged changes, only option available is to stage a change. It would
also be a common use case to restore the changes. (Like how it is done
in uncommitted changes).

## Solution
- A per-hunk Restore button in the inline hunk controls (disabled for
new files)
- A Restore button in the toolbar for selected hunks
- A Restore All button in the toolbar to discard all unstaged changes
- A restore method override on UnstagedDiffDelegate for the Restore
action

## Testing
Tested in locally and ensured both features work

## Self-Review Checklist:

- [ ] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content adheres to Zed's UI standards
([UX/UI](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
and
[icon](https://github.com/zed-industries/zed/blob/main/crates/icons/README.md)
guidelines)
- [ ] Tests cover the new/changed behavior
- [ ] Performance impact has been considered and is acceptable

## Showcase
<img width="1141" height="635" alt="Screenshot 2026-07-09 at 9 00 47 AM"
src="https://github.com/user-attachments/assets/b1d3f091-9f1d-49c6-87e6-9efad25e62dd"
/>

## Note
I am still learning rust bit by bit. Please let me know if something is
massively wrong. This is assisted by AI but reviewed by me with best of
my knowledge.

---

Release Notes:

- Added restore buttons to the unstaged diff view for discarding
unstaged changes.

---------

Signed-off-by: Pranav <pranav10121@gmail.com>
Co-authored-by: Christopher Biscardi <chris@christopherbiscardi.com>
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.

3 participants