Skip to content

Review Diff: file-level Discard (D) reports "Discarded" but leaves staged changes intact for a fully-staged file #2318

Description

@sinelaw

Version: fresh 0.4.0 (built from master @ 1b5d7f8c8)

In Review Diff, the file-level Discard action (D) only reverts a file's
working-tree (unstaged) changes. When a file's changes are entirely
staged (no working-tree diff), confirming the destructive discard dialog
("Discard changes in file — Permanently lose changesThis cannot be
undone.
") does nothing to the staged content, yet the status bar reports
Discarded: <file>. The change remains in the index and on disk and is still
shown in the diff. A user is told an irreversible discard succeeded when in fact
their change is untouched.

Steps to reproduce

  1. Create a git repo and stage a one-line change so the file is fully staged
    with no working-tree diff:
    mkdir /tmp/rdiff && cd /tmp/rdiff && git init -q
    printf 'def add(a, b):\n    return a + b\n' > calc.py
    git add -A && git -c commit.gpgsign=false commit -qm initial
    sed -i 's/return a + b/return a + b  # CHANGED/' calc.py
    git add calc.py
    git status --short        # → "M  calc.py"  (staged, working tree clean)
  2. Launch from that dir (cd /tmp/rdiff inside the shell first), fresh --no-restore.
  3. Command Palette (Ctrl+P) → Review Diff → Enter.
  4. In the STAGED group, move the cursor onto the file's changed hunk line
    (cursor must be on a hunk content row for D to fire).
  5. Press D → a dialog appears: Discard changes in file / Permanently lose changes / Discard "calc.py"? This cannot be undone.
  6. Select Discard changes in file → Enter.

Expected behavior

Either:

  • The staged change is reverted to HEAD (the file goes back to its committed
    state — the obvious meaning of a "this cannot be undone" discard), or
  • If the action is intentionally scoped to working-tree changes only, the dialog
    and result should say so (e.g. "no unstaged changes to discard — unstage
    first"), and it must not report Discarded when nothing was discarded.

For reference, VS Code only offers "Discard Changes" on working-tree changes;
staged changes are unstaged first, and "Discard All Changes" reverts the file to
HEAD. Fresh presents a single generic "Discard changes in file" that implies a
full discard.

Actual behavior

The status bar shows Discarded: calc.py, but:

  • git status --short is still M calc.py (change still staged),
  • git diff --cached still shows the change,
  • the file on disk is unchanged (still contains # CHANGED),
  • the diff in Review Diff still lists the file with its hunk.

Nothing was discarded despite the success message and the irreversible-action
warning. (Verified by git status / git diff --cached before and after.)

Contrast — works for unstaged changes (same session): with the same file
changed but not staged ( M calc.py), D correctly reverts the working
tree to HEAD (Discarded: calc.py, git status clean, file reverted). So the
discard path functions — it simply ignores the index, while the UI claims a full
file discard regardless of staged-vs-unstaged state.

Workaround

Unstage the file first (u/U) so the change becomes a working-tree change,
then D to discard it; or run git restore --staged --worktree <file> from the
shell.


Search queries used (only my own line-level #2317 and the closed hunk-level
#2117 found — both different code paths): review diff discard staged file does nothing, discard changes file staged not reverted, review diff D discard reports discarded no change.

Filed by tui-agent-auto-bug (automated TUI QA agent, Run #36, 2026-06-11).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions