Thread (2 messages) flat view 2 messages, 2 authors, 2025-09-17

Re: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not?

From: D. Ben Knoble <hidden>
Date: 2025-09-17 15:33:22

On Wed, Sep 17, 2025 at 8:12 AM Junio C Hamano [off-list ref] wrote:
"D. Ben Knoble" [off-list ref] writes:
quoted
... " the following
does work in a non-unborn repo to move "newfile" from "untracked" to
"staged" and back again:

    echo >newfile && git add newfile
    git restore --staged newfile

So we don't need "rm --cached" to
quoted
remove <file>
from there [the index] without losing or clobbering the <file> in the working
tree
Now I think about it more, I wonder if "restore --staged" is
misleading and confusing to new users?

When you teach "git restore" what would you tell them?

NAME
       git-restore - Restore working tree files

is how "git restore --help" starts.  It is primarily a tool to let
you repair messed up files in your working tree by copying out of a
known good version from somewhere, be it from the index or from an
existing commit.

But the instruction used to recover from unwanted "git add" to
update the index with modified contents does NOT want to destroy
your files in the working tree.  You want to repair only the index
without touching your working tree files, because you added modified
contents that were not ready to be "staged".  Hence "git restore" is
used with "--staged" option to tell it to do what it was *not*
primarily designed to do, i.e. only touch the index without doing
its usual "Restore working tree files" job.

But there is a lot more appropriate command whose primary focus is
about the index.  "git reset <file>" would grab the contents for the
<file> in HEAD and replace the index entry for <file> with it, which
is exactly how you would move the "Changes to be committed" files to
"Changes not staged for commit" status.

So I think use of "git restore --staged" in the instruction is
wrong, and it should be replaced with "git reset" instead.
As we have in git(1)

   Reset, restore and revert
       There are three commands with similar names: git reset, git restore and
       git revert.

       •   git-revert(1) is about making a new commit that reverts the changes
           made by other commits.

       •   git-restore(1) is about restoring files in the working tree from
           either the index or another commit. This command does not update your
           branch. The command can also be used to restore files in the index
           from another commit.

       •   git-reset(1) is about updating your branch, moving the tip in order
           to add or remove commits from the branch. This operation changes the
           commit history.

           git reset can also be used to restore the index, overlapping with git
           restore.

that already mentions the overlap, I'm inclined to keep "restore
--staged" as a simpler "I'm _restoring_ this file in the index to a
different version." (But my personal "unstage" alias has been "reset
HEAD --" for a long time…) The Examples in git-restore(1) also mention
the reset connection.
quoted
(But the point about having nowhere to restore from stands!)
Yes, and the point about having nowhere to reset from stands for the
state on an unborn branch.  That one needs "rm --cached".
Perhaps more germane to Anselm—I'm still confused that "restore
--staged" can't cope with unborn branches. Sure, there's no "place to
restore from." But the user experience of having 2 different commands
depending on this one state is a bit messy, I think. Wouldn't it be
nice if one command did the right thing (kicking a newly-added file
out of the staging area back to being untracked) in all situations?

IOW, I think "rm --cached" works whether unborn or not—so shouldn't
"restore --staged", too? As I think I saw in a separate reply, plenty
of commands treat the unborn branch as having an empty tree as the
parent. It seems that if "restore --staged" did so, we could unify the
help here and simplify things for the user.

-- 
D. Ben Knoble
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help