Sometimes git suggests git rm --cached
to unstage a file, sometimes git reset HEAD file
. When should I use which?
EDIT:
D:\
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
(use "git rm --cached ..." to unstage)
git is a system of pointers
you do not have a commit yet to change your pointer to
the only way to 'take files out of the bucket being pointed to' is to remove files you told git to watch for changes
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a
git commit -m a
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
(use "git reset HEAD ..." to unstage)
git rm --cached <filePath>
does not unstage a file, it actually stages the removal of the file(s) from the repo (assuming it was already committed before) but leaves the file in your working tree (leaving you with an untracked file).
git reset -- <filePath>
will unstage any staged changes for the given file(s).
That said, if you used git rm --cached
on a new file that is staged, it would basically look like you had just unstaged it since it had never been committed before.
Update git 2.24
In this newer version of git you can use git restore --staged
instead of git reset
.
See git docs.
Just use:
git reset HEAD <filename>
This unstages the file and keeps the changes you did to it, so you can, in turn, change branches if you wanted and git add
those files to another branch instead. All changes are kept.
It would seem to me that git rm --cached <file>
removes the file from the index without removing it from the directory where a plain git rm <file>
would do both, just as an OS rm <file>
would remove the file from the directory without removing its versioning.
I'm surprised noone mentioned the git reflog (http://git-scm.com/docs/git-reflog):
# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}
The reflog is a git history that not only tracks the changes to the repo, but also tracks the user actions (Eg. pull, checkout to different branch, etc) and allows to undo those actions. So instead of unstaging the file that was mistakingly staged, where you can revert to the point where you didn't stage the files.
This is similar to git reset HEAD <file>
but in certain cases may be more granular.
Sorry - not really answering your question, but just pointing yet another way to unstage files that I use quite often (I for one like answers by Ryan Stewart and waldyrious very much.) ;) I hope it helps.
These 2 commands have several subtle differences if the file in question is already in the repo and under version control (previously committed etc.):
git reset HEAD <file>
unstages the file in the current commit.git rm --cached <file>
will unstage the file for future commits also. It's unstaged untill it gets added again with git add <file>
.And there's one more important difference:
git rm --cached <file>
and push your branch to the remote, anyone pulling your branch from the remote will get the file ACTUALLY deleted from their folder, even though in your local working set the file just becomes untracked (i.e. not physically deleted from the folder).This last difference is important for projects which include a config file where each developer on the team has a different config (i.e. different base url, ip or port setting) so if you're using git rm --cached <file>
anyone who pulls your branch will have to manually re-create the config, or you can send them yours and they can re-edit it back to their ip settings (etc.), because the delete only effects people pulling your branch from the remote.