441

EDIT This question can be understood in two ways, and the optimal answer is different in the two cases.

  • Question 1: I added a previously untracked file to the staging area. How can I remove this file from the staging area without removing it from the file system?

    Answer 1: Use the following command, as described in John Feminella's answer:

    git rm --cached <file>
    
  • Question 2: I modified a file already tracked, and added my modifications to the staging area. How can I remove my modifications from the staging area? I.e., how can I unstage my modifications in the file?

    Answer 2: Use the following command, as described in David Underhill's answer:

    git reset <file>
    
hcs42
  • 13,376
  • 6
  • 41
  • 36
  • 6
    Do you mean "reset to what was there before" or "delete, because I don't want that file any more"? – Andrew Aylett Feb 08 '10 at 17:12
  • 1
    In my case it is the same because the file did not exist before... – hcs42 Feb 08 '10 at 17:15
  • @hcs42 the accepted answer is wrong and will result in deleted files for many people. The second most popular answer (`git reset `) is correct. Would it be possible for you to move the green check mark to the correct answer? – Martin Jambon Jul 02 '21 at 00:45
  • 1
    @MartinJambon Thanks for highlighting the problem some people had. The problem was that my question could be understood in two ways. The accepted answer is perfect for the the question I had, but it got some people into trouble who wanted an answer to a different question. I edited the question to include both questions. – hcs42 Jul 03 '21 at 07:03
  • That this apparently same logical operation ("unstage file") requires two completely different commands depending on a presumably irrelevant aspect, is a testament to... I don't know what, sorry, I just want to cry. (I _know_ that there exists a relentlessly logical explanation to this, I know. It just doesn't help...) – Sz. Jan 24 '23 at 20:38

7 Answers7

608

You want:

git rm --cached [file]

If you omit the --cached option, it will also delete it from the working tree. git rm is slightly safer than git reset, because you'll be warned if the staged content doesn't match either the tip of the branch or the file on disk. (If it doesn't, you have to add --force.)

Alex
  • 1,241
  • 13
  • 22
John Feminella
  • 303,634
  • 46
  • 339
  • 357
  • This also works when you have problems with submodules who arent there anymore, then git status does not work, it keeps complaining, this method mentioned here also solves this kind of issue so you can re-add the submodule. – Glenn Plas Oct 08 '12 at 07:49
  • 9
    This also works great if e.g. you accidentally checked in some build intermediates or local configuration files that didn't make it into your .gitignore; use `git rm --cached` to remove them from the repo, add the relevant files or directories to .gitignore, stage and commit as normal. They'll be gone from the repo but remain untouched in your local tree, and you won't accidentally check them in again. – Ionoclast Brigham Dec 07 '14 at 06:27
  • 31
    This also deletes the file from repo (remote) after you commit and push. – powder366 Jun 30 '16 at 06:21
  • 10
    This doesn't remove it from the index, but marks it as deleted in the index. – JotaBe Jul 24 '19 at 08:55
  • 6
    This answer is most likely wrong since it removes a file from the repo (as @powder366 already mentioned) which is not the intended result. – otomo Sep 24 '19 at 10:16
  • 3
    This solution didn't work for me. It marked the specified file as deleted, and then removes it from the local repo. – paiego Nov 18 '19 at 22:00
  • 2
    This shouldn't be accepted answer as it removes file from the repo. – Mateusz Wlodarczyk Jan 10 '20 at 09:47
  • I tried using that command more than once and always ended with files deleted from the system as well. @johnf Can you update/correct your answer please ? It is very misleading with all the upvotes. – Elvynia Mar 15 '21 at 16:53
  • Note that this solution is for files that are previously untracked by git. All of the complaints about removing the file from the repo are because the file they are working with is already being tracked. For that situation, check out the answer by David Underhill. You should always run `git status` and `git diff` before `git commit` to verify that only the changes you want will be included. – Code-Apprentice Mar 14 '23 at 20:26
167

This should unstage a <file> for you (without removing or otherwise modifying the file):

git reset <file>
David Underhill
  • 15,896
  • 7
  • 53
  • 61
7
git reset HEAD <file> 

for removing a particular file from the index.

and

git reset HEAD

for removing all indexed files.

Abdul Gafoor
  • 913
  • 10
  • 12
4

Only use git rm --cached [file] to remove a file from the index.

git reset <filename> can be used to remove added files from the index given the files are never committed.

% git add First.txt
% git ls-files
First.txt
% git commit -m "First"   
% git ls-files            
First.txt
% git reset First.txt
% git ls-files              
First.txt

NOTE: git reset First.txt has no effect on index after the commit.

Which brings me to the topic of git restore --staged <file>. It can be used to (presumably after the first commit) remove added files from the index given the files are never committed.

% git add Second.txt              
% git status        
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
    new file:   Second.txt
% git ls-files       
First.txt
Second.txt
% git restore --staged Second.txt
% git ls-files 
First.txt
% git add Second.txt 
% git commit -m "Second"
% git status            
On branch master
nothing to commit, working tree clean
% git ls-files 
First.txt         
Second.txt
Desktop/Test% git restore --staged .
Desktop/Test% git ls-files
First.txt                   
Second.txt
Desktop/Test% git reset .                    
Desktop/Test% git ls-files
First.txt
Second.txt
% git rm --cached -r .
rm 'First.txt'
rm 'Second.txt'
% git ls-files  

tl;dr Look at last 15 lines. If you don't want to be confused with first commit, second commit, before commit, after commit.... always use git rm --cached [file]

Ahmad Ismail
  • 11,636
  • 6
  • 52
  • 87
4

According to my humble opinion and my work experience with git, staging area is not the same as index. I may be wrong of course, but as I said, my experience in using git and my logic tell me, that index is a structure that follows your changes to your working area(local repository) that are not excluded by ignoring settings and staging area is to keep files that are already confirmed to be committed, aka files in index on which add command was run on. You don't notice and realize that "slight" difference, because you use git commit -a -m "comment" adding indexed and cached files to stage area and committing in one command or using IDEs like IDEA for that too often. And cache is that what keeps changes in indexed files. If you want to remove file from index that has not been added to staging area before, options proposed before match for you, but... If you have done that already, you will need to use

Git restore --staged <file>

And, please, don't ask me where I was 10 years ago... I missed you, this answer is for further generations)

  • "index is a structure that follows your changes to your working area" This is not so, for two reasons: (1) Git does not track files in your working area until you do "git add" on them. (2) Git documentation is clear that the index contains changes on which "git add" was executed: https://git-scm.com/docs/git-add: "git-add - Add file contents to the index". See also: https://www.reddit.com/r/git/comments/2szztw/is_the_index_the_same_as_the_staging_area/ – hcs42 Jul 03 '21 at 07:22
2

Depending on your workflow, this may be the kind of thing that you need rarely enough that there's little point in trying to figure out a command-line solution (unless you happen to be working without a graphical interface for some reason).

Just use one of the GUI-based tools that support index management, for example:

  • git gui <-- uses the Tk windowing framework -- similar style to gitk
  • git cola <-- a more modern-style GUI interface

These let you move files in and out of the index by point-and-click. They even have support for selecting and moving portions of a file (individual changes) to and from the index.


How about a different perspective: If you mess up while using one of the suggested, rather cryptic, commands:

  • git rm --cached [file]
  • git reset HEAD <file>

...you stand a real chance of losing data -- or at least making it hard to find. Unless you really need to do this with very high frequency, using a GUI tool is likely to be safer.


Working without the index

Based on the comments and votes, I've come to realize that a lot of people use the index all the time. I don't. Here's how:

  • Commit my entire working copy (the typical case): git commit -a
  • Commit just a few files: git commit (list of files)
  • Commit all but a few modified files: git commit -a then amend via git gui
  • Graphically review all changes to working copy: git difftool --dir-diff --tool=meld
Brent Bradburn
  • 51,587
  • 17
  • 154
  • 173
  • @Martin: I guess it depends on your workflow. In my approach, I never use the index directly. When I want to save my work, I just do full commits with `git commit -a`. When I was answering this question, it was because I had done (an exotic) "[inverse cherry pick](http://stackoverflow.com/a/1624724/86967)" which puts files in the index for you, but I wanted to edit a file before committing. I took the file out of the index while I edited it so that diffs would work the way that I'm used to. – Brent Bradburn Oct 04 '15 at 16:00
  • my usage case was very narrow and useless indeed: create a branch; add folder filled with files for branch only; switch to master; merge; ops, added wrong folder to master, add it to gitignore; files would not be removed from commit -- granted, a better solution would be just using `rm` straight away but I first thought switching branches wouldn't kill the _ignored_ folder. **but**... I do use github "gui based" tool that's good enough for me and do support some index management except it doesn't support this. so what, should I use 2 gui's for narrow usage? still can't agree with answer. – cregox Feb 23 '16 at 20:41
  • @cregox: I don't know about other platforms, but on typical Linux distros it is trivial to install these bonus GUI tools -- and they may come in handy for other purposes too. In any case, this is just another option for people who prefer a visual approach. – Brent Bradburn Feb 23 '16 at 23:27
  • Just to clarify my above comment: In the answer I suggested two tools that each support this capability. You would only need to use one of them. As a rule, I am a fan of using [GUI tools](https://git-scm.com/download/gui/linux) with Git. Why would you want to manage a [DAG](https://en.wikipedia.org/wiki/Directed_acyclic_graph), such as that created by Git, without the aid of visualization tools. By the way, [`gitk`](https://git-scm.com/docs/gitk) and [`git-gui`](https://git-scm.com/docs/git-gui) are more-or-less standard equipment with Git. – Brent Bradburn Feb 25 '16 at 14:59
  • 3
    This is a decidedly unpopular answer. However, I'm quite sure that the approach I suggest is the right one for some people (myself included). I use one of these tools to manipulate the index a few times per year. – Brent Bradburn Apr 20 '16 at 15:21
  • An alternative, brute force, approach: Perform a commit, followed by an [undo](https://stackoverflow.com/a/16175525). – Brent Bradburn Aug 28 '17 at 16:18
  • This guide repeatedly suggest the use of `git-gui` for working with the index: [Why the index/staging area is so useful](http://gitolite.com/uses-of-index.html) – Brent Bradburn Feb 23 '18 at 23:47
  • 1
    Nowadays programming editors and IDEs are likely to support graphical index manipulation. At least GitHub's [Atom](https://atom.io/) does. – Brent Bradburn Dec 10 '18 at 01:15
  • 1
    I prefer a cli interface over gui any day even though its more dangerous. It will allow me to use git even without gui which I find comforting (instead of being lost when I cant install such tools on a remote server for example). All that said this answer is perfectly valid and doesn't deserve "cli elitist" downvotes, +1 for providing a good gui-alternative! – SidOfc May 02 '20 at 10:22
  • How to use `git difftool` with the index: [How do I show the changes which have been staged?](https://stackoverflow.com/a/45684512/86967) – Brent Bradburn May 02 '20 at 17:49
  • Your IDE (for example Visual Studio Code) probably has this feature too. – Brent Bradburn May 10 '20 at 02:26
1

git rm --cached -r .
Use to remove all files from staging area

  • This does not provide an answer to the question. Once you have sufficient [reputation](https://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](https://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/late-answers/34434359) – treckstar May 26 '23 at 06:26