git rm
will remove entries from the staging area. This is a bit different fromgit reset HEAD
which "unstages" files. By "unstage" I mean it reverts the staging area to what was there before we started modifying things.git rm
on the other hand just kicks the file off the stage entirely, so that it's not included in the next commit snapshot, thereby effectively deleting it.By default, a
git rm file
will remove the file from the staging area entirely and also off your disk > (the working directory). To leave the file in the working directory, you can usegit rm --cached
.
But what exactly is the difference between git rm --cached asd
and git reset head -- asd
?
There are three places where a file, say, can be - the (committed) tree, the index and the working copy. When you just add a file to a folder, you are adding it to the working copy.
When you do something like
git add file
you add it to the index. And when you commit it, you add it to the tree as well.It will probably help you to know the three more common flags in
git reset
:Now, when you do something like
git reset HEAD
, what you are actually doing isgit reset HEAD --mixed
and it will "reset" the index to the state it was before you started adding files / adding modifications to the index (viagit add
). In this case, no matter what the state of the working copy was, you didn't change it a single bit, but you changed the index in such a way that is now in sync with the HEAD of the tree. Whethergit add
was used to stage a previously committed but changed file, or to add a new (previously untracked) file,git reset HEAD
is the exact opposite ofgit add
.git rm
, on the other hand, removes a file from the working directory and the index, and when you commit, the file is removed from the tree as well.git rm --cached
, however, removes the file from the index alone and keeps it in your working copy. In this case, if the file was previously committed, then you made the index to be different from the HEAD of the tree and the working copy, so that the HEAD now has the previously committed version of the file, the index has no file at all, and the working copy has the last modification of it. A commit now will sync the index and the tree, and the file will be removed from the tree (leaving it untracked in the working copy). Whengit add
was used to add a new (previously untracked) file, thengit rm --cached
is the exact opposite ofgit add
(and is pretty much identical togit reset HEAD
).Git 2.25 introduced a new command for these cases,
git restore
, but as of Git 2.28 it is described as “experimental” in the man page, in the sense that the behavior may change.