* Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? @ 2025-09-16 20:29 Anselm Schüler 2025-09-16 20:34 ` Anselm Schüler 2025-09-16 20:52 ` D. Ben Knoble 0 siblings, 2 replies; 7+ messages in thread From: Anselm Schüler @ 2025-09-16 20:29 UTC (permalink / raw) To: git After a new repository has been created, before a commit has been made, when files are staged, git-status suggests using git-rm to unstage files: $ git status [...] No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) [...] After a commit has been made, git-status suggests using git-restore instead: $ git status [...] Changes to be committed: (use "git restore --staged <file>..." to unstage) [...] Why is this the case? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? 2025-09-16 20:29 Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? Anselm Schüler @ 2025-09-16 20:34 ` Anselm Schüler 2025-09-16 20:48 ` Junio C Hamano 2025-09-16 20:52 ` D. Ben Knoble 1 sibling, 1 reply; 7+ messages in thread From: Anselm Schüler @ 2025-09-16 20:34 UTC (permalink / raw) To: git Sorry for that. I apologise for the messed-up formatting. Let’s try that again. — After a new repository has been created, before a commit has been made, when files are staged, git-status suggests using git-rm to unstage files: $ git status [...] No commits yet Changes to be committed: (use "git rm --cached <file>..." to unstage) [...] After a commit has been made, git-status suggests using git-restore instead: $ git status [...] Changes to be committed: (use "git restore --staged <file>..." to unstage) [...] Why is this the case? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? 2025-09-16 20:34 ` Anselm Schüler @ 2025-09-16 20:48 ` Junio C Hamano 0 siblings, 0 replies; 7+ messages in thread From: Junio C Hamano @ 2025-09-16 20:48 UTC (permalink / raw) To: Anselm Schüler; +Cc: git Anselm Schüler <mail@anselmschueler.com> writes: > $ git status > [...] > No commits yet > > Changes to be committed: > (use "git rm --cached <file>..." to unstage) > [...] As this is a very initial commit, any file you are including would only exist in the index and in the working tree files. The index is where you prepare the contents of the commit you are going to create, and "git rm --cached <file>" is the way to remove <file> from there without losing or clobbering the <file> in the working tree. As you do not have a commit yet, you wouldn't have anywhere to "restore" from, would you? > After a commit has been made, git-status suggests using git-restore instead: > > $ git status > [...] > Changes to be committed: > (use "git restore --staged <file>..." to unstage) > [...] Compared to the previous situation, you do have a commit, so you can restore to the version in that commit. During the course of development that led you to this state, you may have added <file> in a commit way before the current commit, and you may have made changes to the <file> multiple times in different commits before the current commit. "git rm --cached <file>" would not be how you would go back to the version in the current commit in such a situation, as it would take you to the state _before_ you originally added that file. You would "restore" the contents in the index to that of the current commit (i.e. HEAD) to go back to the state. So, isn't a short answer to the "why" question, "because that is what you need to do", I guess? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? 2025-09-16 20:29 Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? Anselm Schüler 2025-09-16 20:34 ` Anselm Schüler @ 2025-09-16 20:52 ` D. Ben Knoble 2025-09-17 12:12 ` Junio C Hamano 1 sibling, 1 reply; 7+ messages in thread From: D. Ben Knoble @ 2025-09-16 20:52 UTC (permalink / raw) To: Anselm Schüler; +Cc: git, Junio C Hamano On Tue, Sep 16, 2025 at 4:36 PM Anselm Schüler <mail@anselmschueler.com> wrote: > > After a new repository has been created, before a commit has been made, > when files are staged, git-status suggests using git-rm to unstage > files: $ git status [...] No commits yet Changes to be committed: (use > "git rm --cached <file>..." to unstage) [...] After a commit has been > made, git-status suggests using git-restore instead: $ git status [...] > Changes to be committed: (use "git restore --staged <file>..." to > unstage) [...] Why is this the case? By following builtin/commit.c:cmd_status() to wt-status.c and searching for "rm --cached" (and then blaming), I found the following relevant commits: - 80f537f79c (doc: promote "git restore", 2019-04-25): conversion from reset to restore - 4d4d5726ae (status: show worktree status of conflicted paths separately, 2009-08-05): introduced the is_initial check Unfortunately the latter does not appear to describe or justify the difference. However, a quick test of the kind git init foo echo a > foo/a && git -C foo add a git -C foo restore --staged a gives fatal: could not resolve HEAD Contrary to Junio's mail about "where to restore from," 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 > remove <file> > from there [the index] without losing or clobbering the <file> in the working > tree (But the point about having nowhere to restore from stands!) -- D. Ben Knoble ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? 2025-09-16 20:52 ` D. Ben Knoble @ 2025-09-17 12:12 ` Junio C Hamano 2025-09-17 15:33 ` D. Ben Knoble 0 siblings, 1 reply; 7+ messages in thread From: Junio C Hamano @ 2025-09-17 12:12 UTC (permalink / raw) To: D. Ben Knoble; +Cc: Anselm Schüler, git "D. Ben Knoble" <ben.knoble@gmail.com> writes: > ... " 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 > >> 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. > (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". ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? 2025-09-17 12:12 ` Junio C Hamano @ 2025-09-17 15:33 ` D. Ben Knoble 0 siblings, 0 replies; 7+ messages in thread From: D. Ben Knoble @ 2025-09-17 15:33 UTC (permalink / raw) To: Junio C Hamano; +Cc: Anselm Schüler, git On Wed, Sep 17, 2025 at 8:12 AM Junio C Hamano <gitster@pobox.com> wrote: > > "D. Ben Knoble" <ben.knoble@gmail.com> writes: > > > ... " 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 > > > >> 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. > > (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 ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <8e1905c7-7744-444f-9a39-ca809edb6896@anselmschueler.com>]
* Fwd: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? [not found] <8e1905c7-7744-444f-9a39-ca809edb6896@anselmschueler.com> @ 2025-09-16 21:51 ` Anselm Schüler 2025-09-17 8:03 ` Chris Torek 0 siblings, 1 reply; 7+ messages in thread From: Anselm Schüler @ 2025-09-16 21:51 UTC (permalink / raw) To: git forgot to Reply All 💀 -------- Forwarded Message -------- Subject: Re: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? Date: Tue, 16 Sep 2025 22:56:52 +0200 From: Anselm Schüler <mail@anselmschueler.com> To: Junio C Hamano <gitster@pobox.com> That makes sense, thank you. I suppose this isn’t that interesting, but I find this unintuitive. If it were not for the suggestion in git-status on an empty repository, I would’ve assumed git-rm simply removes the file and “writes” that removal to the staged changes. This seems to be what y’all are describing. But with that suggestion, I was confused, because I assumed git-rm there would be equivalent in some sense to git-restore in a repository with commits. Could git-restore be made to work anyway, by “imagining” a pre-initial-commit commit that has absolutely nothing in it? On 16/09/2025 22:48, Junio C Hamano wrote: > Anselm Schüler <mail@anselmschueler.com> writes: > >> $ git status >> [...] >> No commits yet >> >> Changes to be committed: >> (use "git rm --cached <file>..." to unstage) >> [...] > As this is a very initial commit, any file you are including would > only exist in the index and in the working tree files. The index is > where you prepare the contents of the commit you are going to > create, and "git rm --cached <file>" is the way to remove <file> > from there without losing or clobbering the <file> in the working > tree. As you do not have a commit yet, you wouldn't have anywhere > to "restore" from, would you? > >> After a commit has been made, git-status suggests using git-restore >> instead: >> >> $ git status >> [...] >> Changes to be committed: >> (use "git restore --staged <file>..." to unstage) >> [...] > Compared to the previous situation, you do have a commit, so you can > restore to the version in that commit. During the course of > development that led you to this state, you may have added <file> in > a commit way before the current commit, and you may have made > changes to the <file> multiple times in different commits before the > current commit. "git rm --cached <file>" would not be how you would > go back to the version in the current commit in such a situation, as > it would take you to the state _before_ you originally added that > file. You would "restore" the contents in the index to that of the > current commit (i.e. HEAD) to go back to the state. > > So, isn't a short answer to the "why" question, "because that is > what you need to do", I guess? ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? 2025-09-16 21:51 ` Fwd: " Anselm Schüler @ 2025-09-17 8:03 ` Chris Torek 0 siblings, 0 replies; 7+ messages in thread From: Chris Torek @ 2025-09-17 8:03 UTC (permalink / raw) To: Anselm Schüler; +Cc: git [resend as plain text] On Tue, Sep 16, 2025 at 2:53 PM Anselm Schüler <mail@anselmschueler.com> wrote: > ... I would’ve assumed git-rm simply removes the file > and “writes” that removal to the staged changes. More precisely, it removes the file from the working tree and removes the index entry that would cause the index copy of the file to be in the next commit. > This seems to be what y’all are > describing. But with that suggestion, I was confused, because I assumed > git-rm there would be equivalent in some sense to git-restore in a > repository with commits. > > Could git-restore be made to work anyway, by “imagining” a > pre-initial-commit commit that has absolutely nothing in it? Yes, and in fact a number of Git internal operations work this way, by pretending the commit before the first commit has as its tree the empty tree. If `git restore` did that here it would Just Work. (This is part of why the empty tree always seems to exist.) Whether this is a Good Idea, I leave to others to judge, as I'm too well steeped in Git internals to tell any more. :-) Chris ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-09-17 15:33 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-16 20:29 Why does git-status suggest different commands to unstage files depending on whether there is a commit yet or not? Anselm Schüler
2025-09-16 20:34 ` Anselm Schüler
2025-09-16 20:48 ` Junio C Hamano
2025-09-16 20:52 ` D. Ben Knoble
2025-09-17 12:12 ` Junio C Hamano
2025-09-17 15:33 ` D. Ben Knoble
[not found] <8e1905c7-7744-444f-9a39-ca809edb6896@anselmschueler.com>
2025-09-16 21:51 ` Fwd: " Anselm Schüler
2025-09-17 8:03 ` Chris Torek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).