9782

I mistakenly added files to Git using the command:

git add myfile.txt

I have not yet run git commit. Is there a way to undo this, so these files won't be included in the commit?

Braiam
  • 4,345
  • 11
  • 47
  • 69
paxos1977
  • 135,245
  • 26
  • 85
  • 125
  • 32
    Starting with Git v1.8.4, all the answers below that use `HEAD` or `head` can now use `@` in place of `HEAD` instead. See [this answer (last section)](http://stackoverflow.com/questions/964876/head-and-orig-head-in-git/964927#964927) to learn why you can do that. –  Jul 26 '13 at 02:04
  • 3
    I made a little summery which shows all ways to unstage a file: http://stackoverflow.com/questions/6919121/why-are-there-2-ways-to-unstage-a-file-in-git/16044987#16044987 – Daniel Alder Apr 26 '14 at 12:09
  • 6
    Why not git checkout? – Erik Reppen Sep 05 '16 at 14:57
  • 15
    @ErikReppen `git checkout` does not remove staged changes from the commit index. It only reverts un-staged changes to the last committed revision - which by the way is not what I want either, I want those changes, I just want them in a later commit. – paxos1977 Sep 06 '16 at 21:08
  • 5
    If you use Eclipse, it is as simple as unchecking the files in the commit dialogue box – Hamzahfrq Nov 17 '16 at 12:49
  • 2
    This is a great resource straight from Github: [How to undo \(almost\) anything with Git](https://github.com/blog/2019-how-to-undo-almost-anything-with-git) – jasonleonhard Feb 03 '17 at 21:13
  • 1
    Before you post a new answer, consider there are already 25+ answers for this question. Make sure that your answer contributes what is not among existing answers – Sazzad Hissain Khan Jun 15 '17 at 15:29
  • I wish I could upvote this every time I have to come back here to refer to it – scubbo Feb 02 '18 at 22:59
  • git remove myfile.txt – Simon Berton Feb 13 '18 at 11:48
  • I always make this work by running `git reset `. For more info be sure to take a look at [this article](https://kolosek.com/git-commands-tutorial-part2/). – Nesha Zoric May 07 '18 at 12:23
  • if readers like to use GUI, you can right-click a file and click reset, or unstage – Uğur Gümüşhan Mar 23 '20 at 09:04
  • ```git rm --cached ``` **unstages and untracks** (marked for removal on next commit) a given file, while ```git reset HEAD ``` just **unstages** the file – Dennis Jan 30 '21 at 22:26

37 Answers37

11540

You can undo git add before commit with

git reset <file>

which will remove it from the current index (the "about to be committed" list) without changing anything else.

You can use

git reset

without any file name to unstage all due changes. This can come in handy when there are too many files to be listed one by one in a reasonable amount of time.

In old versions of Git, the above commands are equivalent to git reset HEAD <file> and git reset HEAD respectively, and will fail if HEAD is undefined (because you haven't yet made any commits in your repository) or ambiguous (because you created a branch called HEAD, which is a stupid thing that you shouldn't do). This was changed in Git 1.8.2, though, so in modern versions of Git you can use the commands above even prior to making your first commit:

"git reset" (without options or parameters) used to error out when you do not have any commits in your history, but it now gives you an empty index (to match non-existent commit you are not even on).

Documentation: git reset

Manu Sharma
  • 467
  • 5
  • 15
genehack
  • 118,728
  • 1
  • 20
  • 24
  • 112
    Of course, this is not a true undo, because if the wrong `git add` overwrote a previous staged uncommited version, we can't recover it. I tried to clarify this in my answer below. – leonbloy May 06 '13 at 19:10
  • 10
    `git reset HEAD *.ext` where `ext` is the files of the given extension you want to unadd. For me it was `*.bmp` & `*.zip` – boulder_ruby Nov 26 '13 at 14:25
  • 1
    git reset said it undid the changes but when I proceeded to do another git status, they still showed modified – PositiveGuy Oct 16 '15 at 03:39
  • 2
    So the opposite of "add" is "reset"? What about "remove"? – Jonny Feb 17 '16 at 05:53
  • 22
    @Jonny, the index (aka staging area) contains *all* the files, not just changed files. It "starts life" (when you check out a commit or clone a repo) as a copy of all the files in the commit pointed to by HEAD. So if you *remove* a file from the index (`git rm --cached`) it means you are preparing to make a commit that *deletes* that file. `git reset HEAD ` on the other hand will copy the file from HEAD to the index, so that the next commit won't show any changes being made to that file. – Wildcard Mar 16 '16 at 12:27
  • 14
    I just discovered that there is a `git reset -p` just like `git add -p`. This is awesome! – donquixote Jul 17 '16 at 23:23
  • 2
    `-p` most definitely is awesome, and it's used in a lot of git commands (not just reset and add). But to answer @WeDoTDD.com and @Johnny, `git reset` by itself just clears whether Git "knows about" the changes; it doesn't clear the changes themselves. To do that you need to do `git checkout someFile.txt` (for individual files) or `git reset --hard` (to wipe everything clean). There's no going back from either of these commands though, so be very careful when using them. – machineghost Dec 15 '16 at 18:33
  • 1
    but 'git reset file' removes other files that had been staged for commit too. not good. – Arthur Feb 17 '17 at 16:29
  • 15
    You actually **can recover overwriten previously staged but uncommited changes** but not in a userfriendly way and not 100% secure (at least none I had found): goto .git/objects, search for files created at the time of `git add` you want to recover (`61/3AF3...` -> object id `613AF3...`), then `git cat-file -p ` (might be worth it to recover several hours of work but also a lesson to commit more often...) – Peter Schneider Jul 31 '17 at 14:03
  • 1
    Another way to __recover changes that were staged but not committed and then overwritten__ by e.g. another `git add` is via `git fsck --unreachable` that will list all unreachable obj, which you can then inspect by `git show SHA-1_ID` or `git fsck --lost-found` that will >Write dangling objects into `.git/lost-found/commit/` or `.git/lost-found/other/`, depending on type. See also `git fsck --help` – iolsmit Apr 27 '18 at 15:27
  • 1
    As of git 2.23.0, there is now `"git restore --staged ..." to unstage`. See https://stackoverflow.com/a/16044987/40422 – Bill Hoag Nov 20 '19 at 19:31
  • I have also added some files from a common library to the stage. Since, it is an angular app, so I had to use `git reset */commonlib/styles/*.scss` to locate all such files and it worked. – akgupta Jan 22 '20 at 19:22
  • Well explained...helpful for newer – Satish Hawalppagol Aug 06 '20 at 06:20
  • Thanks this was easy to understand and helpful. – wesley franks Aug 18 '20 at 01:25
  • I don't know if I did this right, but `git reset ` seemed to also delete the file from my file system as well, which is obviously not what you want. – crobar Oct 14 '20 at 10:18
2251

You want:

git rm --cached <added_file_to_undo>

Reasoning:

When I was new to this, I first tried

git reset .

(to undo my entire initial add), only to get this (not so) helpful message:

fatal: Failed to resolve 'HEAD' as a valid ref.

It turns out that this is because the HEAD ref (branch?) doesn't exist until after the first commit. That is, you'll run into the same beginner's problem as me if your workflow, like mine, was something like:

  1. cd to my great new project directory to try out Git, the new hotness
  2. git init
  3. git add .
  4. git status

    ... lots of crap scrolls by ...

    => Damn, I didn't want to add all of that.

  5. google "undo git add"

    => find Stack Overflow - yay

  6. git reset .

    => fatal: Failed to resolve 'HEAD' as a valid ref.

It further turns out that there's a bug logged against the unhelpfulness of this in the mailing list.

And that the correct solution was right there in the Git status output (which, yes, I glossed over as 'crap)

...
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
...

And the solution indeed is to use git rm --cached FILE.

Note the warnings elsewhere here - git rm deletes your local working copy of the file, but not if you use --cached. Here's the result of git help rm:

--cached Use this option to unstage and remove paths only from the index. Working tree files, whether modified or not, will be left.

I proceed to use

git rm --cached .

to remove everything and start again. Didn't work though, because while add . is recursive, turns out rm needs -r to recurse. Sigh.

git rm -r --cached .

Okay, now I'm back to where I started. Next time I'm going to use -n to do a dry run and see what will be added:

git add -n .

I zipped up everything to a safe place before trusting git help rm about the --cached not destroying anything (and what if I misspelled it).

codeforester
  • 28,846
  • 11
  • 78
  • 104
Rhubarb
  • 31,739
  • 2
  • 42
  • 33
  • Doesn't just "git reset" without . do what you want, or am I missing something? – ustun Nov 11 '09 at 12:21
  • 19
    Hah. I followed this same process. Except I gave up and said `rm -rf .git`, `git init` because I didn't trust `git rm --cached` to keep my working copy. It says a little for how git is still overly complex in some places. `git unstage` should just be a stock standard command, I don't care if I can add it as an alias. – Adrian Macneil Mar 29 '11 at 03:45
  • 2
    Did this and it deleted all my other existing files - unchanged - from the git backup. Re-adding them makes everything larger and destroys the proper history. Git is totally an unfinished project. – SamGoody Jun 01 '11 at 09:09
  • in recent versions of git (v1.7.1.1 tested ) `git rm -r --cached .` works fine – Tom Davies Nov 22 '11 at 15:23
  • 1
    If you like `git reset`, try **`git reset *`** instead of `git reset .` - it un-stages all you previously staged files. – Marius Butuc Dec 09 '11 at 21:58
  • 1
    Brilliant answer that described my workflow exactly. It really needs to be the accepted answer to be topmost as this Q is what is top of the search results for "git unstage". – Henric Dec 16 '11 at 09:36
  • 1
    Instead of the dry run, walk through the add with `git add -p` – jlundqvist Apr 28 '12 at 22:05
  • 5
    For me git says `git reset HEAD ...` – drahnr Sep 12 '12 at 06:50
  • You also could use `git stash/git stash pop` to avoid zipping/backing up everything – chachan Nov 03 '12 at 19:05
  • 21
    git rm --cached is actually the correct answer, if it is the initial import of into the repository. If you're trying to unstage a change to the file, git reset is the correct answer. People saying that this answer is wrong are thinking of a different question. – Barry Kelly Feb 28 '13 at 22:14
  • 15
    This will actually work, but **only** on the first commit, where the file didn't exist before, or where the `git add` command added new files, **but not** changes to existing files. – naught101 Apr 10 '13 at 02:33
  • 1
    I certainly feel if this is a totally new repository, removing the `.git` directory and initialising again is the best way. For cases in a well-used repo where you just accidentally added a single file, `git rm --cached ` seems best although I get a scary `delete mode 100644 file` after my commit. – deed02392 Jul 14 '13 at 22:28
  • 3
    according to `git status` output of git version 1.8.1.4 the correct way to unstage new files is: `git reset HEAD ...` – akostadinov Aug 28 '13 at 18:25
  • 5
    just goes to show how unintuitive and convoluted git is. instead of having parallel "undo" commands, you have to find out how to undo them. Like trying to free your leg in quick sand, and then getting your arm stuck, then getting your other arm stuck... every command should be done through GUI, with dropdown menus items for the options... Think of all the UI, productivity gains we've had, but we have this mess of a retro command line interface. It's not like the git GUI programs make this any more intuitive. – ahnbizcad May 24 '14 at 10:54
  • 2
    @BarryKelly no it is not the correct answer. What you actually want to do is either `git reset` to undo all added files or `git reset ` to undo a specific added file. `git rm --cached` may work on the surface but what actually happens is it removes it from the tracking history as well which is not what you would want to do, unless, you added that file to a gitignore file where that file shouldn't have been tracked in the first place then in that case it would be ok. – JoeMoe1984 Jun 02 '14 at 21:14
  • @JoeMoe1984 git reset doesn't work on empty repos (initial imports) – Barry Kelly Jun 03 '14 at 13:40
  • @BarryKelly I tried to edit my comment as I reread yours but I was too late. I missed that part of what you wrote ;). But yeah you're right, that would be another instance to use `git rm --cached` – JoeMoe1984 Jun 03 '14 at 17:33
  • When intially populating a git repository, "git reset" from the top answer doesn't work: failed to resolve HEAD. We added a single file too many to the initial commit. As suggested by this answer, in that case "git rm --cached " works for me. Maybe "git rm --cached ." does more than is intended for some people, but (as suggested by git status), git rm --cached works.... – rew Oct 20 '15 at 11:31
  • 2
    Why not just delete the hidden .git folder lol.. and do git init again... (assuming you're making the git repo for the FIRST time and have not done any commits) – Kevin Lee Apr 05 '16 at 14:16
  • 2
    If the files have not yet in index, use `git rm --cache `, if the files already in index, but you don't want them to be in this commit, use `git reset ` – Ding-Yi Chen Oct 20 '16 at 01:46
  • This may have been applicable at the time of writing but seems to work now. – Thomas Weller Jun 08 '17 at 10:20
  • 1
    This is also a wrong answer. I don't know why people post answers, and even less why they upvote wrong answers.... – Vladimir Despotovic Sep 27 '18 at 13:22
  • 2
    This command CLEARS / DELETES STUFF IN THE INDEX. What the OP and other people actually want is to UNDO THE CHANGES IN THE INDEX and NOT DELETE STUFF. Git reset . is the correct answer. – bhavya_w Feb 18 '19 at 08:43
  • 1
    @ahnbizcad ...well, once you know what you're doing, it's much easier,...and I find the GUI too bloated and too much mouse movement...so it's a matter of opinion. – TheTechRobo36414519 Jun 29 '20 at 17:15
  • I just discovered that there is a git reset -p just like git add -p. This is awesome! – Ahmad Dec 28 '20 at 23:56
563

If you type:

git status

Git will tell you what is staged, etc., including instructions on how to unstage:

use "git reset HEAD <file>..." to unstage

I find Git does a pretty good job of nudging me to do the right thing in situations like this.

Note: Recent Git versions (1.8.4.x) have changed this message:

(use "git rm --cached <file>..." to unstage)
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Paul Beckingham
  • 13,460
  • 5
  • 30
  • 67
  • 23
    The message will be different depending on whether the `add`ed file was already being tracked (the `add` only saved a new version to the cache - here it will show your message). Elsewhere, if the file was not previously staged, it will display `use "git rm --cached ..." to unstage` – leonbloy May 06 '13 at 18:25
  • Great! The `git reset HEAD ` one is the only one that will work in case you want to unstage a file delete – skerit Feb 24 '18 at 00:25
  • 2
    My git version 2.14.3 says `git reset HEAD` to unstage. – SilverWolf Apr 23 '18 at 19:16
  • Since Git v2.23 the message has changed yet again. It now says `git restore --staged `. See [my answer below](https://stackoverflow.com/a/62569076/9210961) for an update. – prosoitos Nov 19 '20 at 17:02
261

To clarify: git add moves changes from the current working directory to the staging area (index).

This process is called staging. So the most natural command to stage the changes (changed files) is the obvious one:

git stage

git add is just an easier-to-type alias for git stage

Pity there is no git unstage nor git unadd commands. The relevant one is harder to guess or remember, but it is pretty obvious:

git reset HEAD --

We can easily create an alias for this:

git config --global alias.unadd 'reset HEAD --'
git config --global alias.unstage 'reset HEAD --'

And finally, we have new commands:

git add file1
git stage file2
git unadd file2
git unstage file1

Personally I use even shorter aliases:

git a # For staging
git u # For unstaging
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
takeshin
  • 44,484
  • 28
  • 112
  • 160
  • 4
    "moves"? This would indicate it has gone from the working directory. That's not the case. – Thomas Weller Jun 08 '17 at 09:18
  • 4
    Why is it obvious? – Lenar Hoyt Jun 23 '17 at 18:25
  • Actually, `git stage` is the alias for `git add`, which is the historic command, both on Git and other SCM. It has been added in december 2008 with commit 11920d28da in the "Git's git repository", if I can say. – Obsidian Sep 12 '18 at 18:13
  • 1
    This might be unrelated, but I've found validating the file before even adding to be a useful idea, something like check-command filename && git add filename, I replaced git with a shorter g in my machine, and so far it has worked ok for me: https://github.com/dataf3l/g , I don't know if this will be useful to somebody, but I'll put it here in the hopes it saves some people's time. – Felipe Valdes Jul 12 '19 at 10:21
180

An addition to the accepted answer, if your mistakenly-added file was huge, you'll probably notice that, even after removing it from the index with 'git reset', it still seems to occupy space in the .git directory.

This is nothing to be worried about; the file is indeed still in the repository, but only as a "loose object". It will not be copied to other repositories (via clone, push), and the space will be eventually reclaimed - though perhaps not very soon. If you are anxious, you can run:

git gc --prune=now

Update (what follows is my attempt to clear some confusion that can arise from the most upvoted answers):

So, which is the real undo of git add?

git reset HEAD <file> ?

or

git rm --cached <file>?

Strictly speaking, and if I'm not mistaken: none.

git add cannot be undone - safely, in general.

Let's recall first what git add <file> actually does:

  1. If <file> was not previously tracked, git add adds it to the cache, with its current content.

  2. If <file> was already tracked, git add saves the current content (snapshot, version) to the cache. In Git, this action is still called add, (not mere update it), because two different versions (snapshots) of a file are regarded as two different items: hence, we are indeed adding a new item to the cache, to be eventually committed later.

In light of this, the question is slightly ambiguous:

I mistakenly added files using the command...

The OP's scenario seems to be the first one (untracked file), we want the "undo" to remove the file (not just the current contents) from the tracked items. If this is the case, then it's ok to run git rm --cached <file>.

And we could also run git reset HEAD <file>. This is in general preferable, because it works in both scenarios: it also does the undo when we wrongly added a version of an already tracked item.

But there are two caveats.

First: There is (as pointed out in the answer) only one scenario in which git reset HEAD doesn't work, but git rm --cached does: a new repository (no commits). But, really, this a practically irrelevant case.

Second: Be aware that git reset HEAD can't magically recover the previously cached file contents, it just resynchronises it from the HEAD. If our misguided git add overwrote a previous staged uncommitted version, we can't recover it. That's why, strictly speaking, we cannot undo [*].

Example:

$ git init
$ echo "version 1" > file.txt
$ git add file.txt   # First add of file.txt
$ git commit -m 'first commit'
$ echo "version 2" > file.txt
$ git add  file.txt   # Stage (don't commit) "version 2" of file.txt
$ git diff --cached file.txt
-version 1
+version 2
$ echo "version 3" > file.txt
$ git diff  file.txt
-version 2
+version 3
$ git add  file.txt    # Oops we didn't mean this
$ git reset HEAD file.txt  # Undo?
$ git diff --cached file.txt  # No dif, of course. stage == HEAD
$ git diff file.txt   # We have irrevocably lost "version 2"
-version 1
+version 3

Of course, this is not very critical if we just follow the usual lazy workflow of doing 'git add' only for adding new files (case 1), and we update new contents via the commit, git commit -a command.


* (Edit: the above is practically correct, but still there can be some slightly hackish/convoluted ways for recovering changes that were staged, but not committed and then overwritten - see the comments by Johannes Matokic and iolsmit)

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
leonbloy
  • 65,169
  • 19
  • 130
  • 176
  • 5
    Strictly speaking there is a way to recover an already staged file that was replaced with git add. As you mention git add creates an git object for that file that will become a loose object not only when removing the file completely but also when being overwritten with new content. But there is no command to automatically recover it. Instead the file has to be identified and extracted manually or with tools written only for this case (libgit2 will allow this). But this will only pay out if the file is very important and big and could not be rebuild by editing the previous version. – Johannes Matokic Dec 06 '17 at 13:07
  • 3
    To correct myself: Once the loose object file is found (use meta-data like creation date/time) `git cat-file` could be used to recover its content. – Johannes Matokic Dec 06 '17 at 13:22
  • 5
    Another way to __recover changes that were staged but not committed and then overwritten__ by e.g. another `git add` is via `git fsck --unreachable` that will list all unreachable obj, which you can then inspect by `git show SHA-1_ID` or `git fsck --lost-found` that will >Write dangling objects into `.git/lost-found/commit/` or `.git/lost-found/other/`, depending on type. See also `git fsck --help` – iolsmit Apr 27 '18 at 15:29
142

Undo a file which has already been added is quite easy using Git. For resetting myfile.txt, which have already been added, use:

git reset HEAD myfile.txt

Explanation:

After you staged unwanted file(s), to undo, you can do git reset. Head is head of your file in the local and the last parameter is the name of your file.

I have created the steps in the image below in more details for you, including all steps which may happen in these cases:

git reset HEAD file

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Alireza
  • 83,698
  • 19
  • 241
  • 152
102
git rm --cached . -r

will "un-add" everything you've added from your current directory recursively

fedorqui 'SO stop harming'
  • 228,878
  • 81
  • 465
  • 523
braitsch
  • 12,644
  • 5
  • 39
  • 33
94

Run

git gui

and remove all the files manually or by selecting all of them and clicking on the unstage from commit button.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Khaja Minhajuddin
  • 6,236
  • 6
  • 43
  • 44
93

Git has commands for every action imaginable, but it needs extensive knowledge to get things right and because of that it is counter-intuitive at best...

What you did before:

  • Changed a file and used git add ., or git add <file>.

What you want:

  • Remove the file from the index, but keep it versioned and left with uncommitted changes in working copy:

     git reset HEAD <file>
    
  • Reset the file to the last state from HEAD, undoing changes and removing them from the index:

     # Think `svn revert <file>` IIRC.
     git reset HEAD <file>
     git checkout <file>
    
     # If you have a `<branch>` named like `<file>`, use:
     git checkout -- <file>
    

    This is needed since git reset --hard HEAD won't work with single files.

  • Remove <file> from index and versioning, keeping the un-versioned file with changes in working copy:

     git rm --cached <file>
    
  • Remove <file> from working copy and versioning completely:

     git rm <file>
    
sjas
  • 15,508
  • 11
  • 75
  • 80
  • 1
    I can't under stand the difference of 'git reset head ' and 'git rm --cached . Could you explain it? – jeswang Aug 14 '13 at 00:39
  • 6
    @jeswang files are either 'known' to git (changes in them are being tracked.), or they are not 'versioned'. `reset head` undoes your current changes, but the file is still being monitored by git. `rm --cached` takes the file out of versioning, so git no longer checks it for changes (and also removes eventually indexed present changes, told to git by the prior `add`), but the changed file will be kept in your working copy, that is in you file folder on the HDD. – sjas Aug 15 '13 at 15:09
  • 3
    The difference is `git reset HEAD ` is temporary - the command will be applied to the next commit only, but `git rm --cached ` will unstage untill it gets added again with `git add `. Also, `git rm --cached ` means if you push that branch to the remote, anyone pulling the branch will get the file ACTUALLY deleted from their folder. – DrewT Aug 10 '14 at 19:54
91

The question is not clearly posed. The reason is that git add has two meanings:

  1. adding a new file to the staging area, then undo with git rm --cached file.
  2. adding a modified file to the staging area, then undo with git reset HEAD file.

If in doubt, use

git reset HEAD file

Because it does the expected thing in both cases.

Warning: if you do git rm --cached file on a file that was modified (a file that existed before in the repository), then the file will be removed on git commit! It will still exist in your file system, but if anybody else pulls your commit, the file will be deleted from their work tree.

git status will tell you if the file was a new file or modified:

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    new file:   my_new_file.txt
    modified:   my_modified_file.txt
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Michael_Scharf
  • 29,028
  • 15
  • 60
  • 87
  • 8
    +1. An extraordinary number of highly-upvoted answers and comments on this page are just flat-out wrong about the behaviour of `git rm --cached somefile`. I hope this answer makes its way up the page to a prominent position where it can protect newbies from being misled by all the false claims. – Mark Amery Oct 30 '15 at 23:44
  • one of the best answers on here, sadly it is quite low on the list – Creos Jun 10 '19 at 01:10
67

If you're on your initial commit and you can't use git reset, just declare "Git bankruptcy" and delete the .git folder and start over

joppiesaus
  • 4,888
  • 3
  • 21
  • 35
Ana Betts
  • 71,086
  • 16
  • 135
  • 201
  • 5
    One tip is to copy your .git/config file if you have added remote origin, before deleting the folder. – Tiago Mar 08 '10 at 23:15
  • 4
    @ChrisJohnsen comment is spot on. Sometimes, you want to commit all files except one: `git add -A && git rm --cached EXCLUDEFILE && git commit -m 'awesome commit'` (This also works when there's no previous commits, re `Failed to resolve 'HEAD'` problem) –  Mar 29 '13 at 04:20
65

As per many of the other answers, you can use git reset

BUT:

I found this great little post that actually adds the Git command (well, an alias) for git unadd: see git unadd for details or..

Simply,

git config --global alias.unadd "reset HEAD"

Now you can

git unadd foo.txt bar.txt

Alternatively / directly:

git reset HEAD foo.txt bar.txt
matinict
  • 2,114
  • 2
  • 24
  • 34
electblake
  • 1,707
  • 16
  • 25
49

Use git add -i to remove just-added files from your upcoming commit. Example:

Adding the file you didn't want:

$ git add foo
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   foo
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]#

Going into interactive add to undo your add (the commands typed at git here are "r" (revert), "1" (first entry in the list revert shows), 'return' to drop out of revert mode, and "q" (quit):

$ git add -i
           staged     unstaged path
  1:        +1/-0      nothing foo

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> r
           staged     unstaged path
  1:        +1/-0      nothing [f]oo
Revert>> 1
           staged     unstaged path
* 1:        +1/-0      nothing [f]oo
Revert>> 
note: foo is untracked now.
reverted one path

*** Commands ***
  1: [s]tatus     2: [u]pdate     3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff       7: [q]uit       8: [h]elp
What now> q
Bye.
$

That's it! Here's your proof, showing that "foo" is back on the untracked list:

$ git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
# [...]
#       foo
nothing added to commit but untracked files present (use "git add" to track)
$
the Tin Man
  • 150,910
  • 39
  • 198
  • 279
Alex North-Keys
  • 3,871
  • 1
  • 18
  • 22
45

git remove or git rm can be used for this, with the --cached flag. Try:

git help rm
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
gnud
  • 73,015
  • 5
  • 56
  • 76
  • 10
    Isn't this going to remove the file altogether? – Willa Aug 26 '15 at 05:29
  • 10
    `git rm --cached ...` will remove files from a git repo. They'll still exist on your computer, but this is VERY different from unstaging *changes* to a file. For anyone stumbling upon this, it isn't a valid answer to the question. – Addison Dec 17 '18 at 20:02
41

Here's a way to avoid this vexing problem when you start a new project:

  • Create the main directory for your new project.
  • Run git init.
  • Now create a .gitignore file (even if it's empty).
  • Commit your .gitignore file.

Git makes it really hard to do git reset if you don't have any commits. If you create a tiny initial commit just for the sake of having one, after that you can git add -A and git reset as many times as you want in order to get everything right.

Another advantage of this method is that if you run into line-ending troubles later and need to refresh all your files, it's easy:

  • Check out that initial commit. This will remove all your files.
  • Then check out your most recent commit again. This will retrieve fresh copies of your files, using your current line-ending settings.
Ryan Lundy
  • 187,365
  • 35
  • 174
  • 206
  • 1
    Confirmed! Tried a git reset after a git add . and git was complaining about corrupt HEAD. Following your advice, I could git add & reset back and forth with no problems :) – Kounavi Oct 03 '12 at 21:32
  • 1
    The second part works, but it is a bit clumsy. How line endings are handled, depends on `autocrlf` value... This won't work in every project, depending the settings. – sjas Mar 29 '13 at 11:26
  • 1
    This answer was reasonable at the time it was posted, but is now obsolete; `git reset somefile` and `git reset` both work prior to making the first commit, now. This has been the case since several Git releases back. – Mark Amery Oct 30 '15 at 23:38
  • @MarkAmery, you may be right (it'd be cool if you posted a source for your assertion), but there's still value in starting your repo with a clean commit or two. – Ryan Lundy Oct 31 '15 at 20:01
38

Note that if you fail to specify a revision then you have to include a separator. Example from my console:

git reset <path_to_file>
fatal: ambiguous argument '<path_to_file>': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions

git reset -- <path_to_file>
Unstaged changes after reset:
M    <path_to_file>

(Git version 1.7.5.4)

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
powlo
  • 2,186
  • 2
  • 25
  • 34
  • 2
    I tried `git reset ` and it works just fine without a separator. I'm also using git 1.9.0. Maybe it doesn't work in older versions? –  Apr 05 '14 at 05:32
37

Maybe Git has evolved since you posted your question.

$> git --version
git version 1.6.2.1

Now, you can try:

git reset HEAD .

This should be what you are looking for.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Kokotte23
  • 387
  • 3
  • 2
  • 2
    Sure, but then you have the followup question of how one should unadd one of *two* (or more) files added. The "git reset" manual does mention that "git reset " is the opposite of "git add ", however. – Alex North-Keys May 15 '13 at 13:36
33

To remove new files from the staging area (and only in case of a new file), as suggested above:

git rm --cached FILE

Use rm --cached only for new files accidentally added.

Ran
  • 7,083
  • 12
  • 56
  • 72
30

To reset every file in a particular folder (and its subfolders), you can use the following command:

git reset *
Zorayr
  • 20,232
  • 5
  • 111
  • 102
  • 4
    Actually, this does not reset every file because * uses shell expansion and it ignores dotfiles (and dot-directories). – Luc May 04 '14 at 23:20
  • You can run `git status` to see anything remaining and reset it manually i.e. `git reset file`. – Zorayr May 07 '14 at 15:23
29

Use the * command to handle multiple files at a time:

git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*

etc.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
boulder_ruby
  • 33,076
  • 8
  • 66
  • 91
  • 3
    Mind that * will usually not include dotfiles or 'dot-directories' unless you explicitly specify `.*` or `.*.prj` – Luc May 04 '14 at 23:21
27

Just type git reset it will revert back and it is like you never typed git add . since your last commit. Make sure you have committed before.

Piyush
  • 3,697
  • 7
  • 31
  • 63
Donovan
  • 295
  • 3
  • 3
  • As it happens, there was a last commit... but I was specifically asking about removing a single file from the commit, not every file from the commit. – paxos1977 Jan 31 '13 at 16:21
26

Suppose I create a new file, newFile.txt:

Enter image description here

Suppose I add the file accidentally, git add newFile.txt:

Enter image description here

Now I want to undo this add, before commit, git reset newFile.txt:

Enter image description here

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Vidura Mudalige
  • 750
  • 2
  • 14
  • 26
  • Suppose I am at 1st pic meaning meaning I have not even did "git.add". Also, I not at all want all this change. I mean when I do git status, it should not show any red files. I mean it should be in sync as if there was not a single file altered since the last git push. how to achieve that. – Unbreakable Mar 26 '17 at 00:59
  • SO suppose you are just at step first. And you want to get rid of all the changes you have done which is making "newFile.txt" to come up as red. – Unbreakable Mar 26 '17 at 01:00
  • When I do git status. I should not see any change at all. All the red files should get reverted. – Unbreakable Mar 26 '17 at 01:00
  • Hi, I think your question is how to remove untracked files from the current tree. For that, you can use "git clean -f -d". This will remove untracked directories as well. – Vidura Mudalige Mar 26 '17 at 10:19
  • If you don't want to delete the untracked files, just ignore "-f" flag. – Vidura Mudalige Mar 26 '17 at 10:20
  • It did not work. Suppose I did a git push. Now if I add a single line in my code and check git status. It will show a file in Red colour. Suppose I do not want that one line change at all. One option is I can do cntrl + z. But I want git to do that for me. I want my local project to get in sync with the master repo. I mean when I do "git status" then I should see message as "Its in sync with the master". And when I open my code I should have a message like "some external source is making changes" and when I say "Yes" to that prompt then the one line change that I had made shold be gone. – Unbreakable Mar 26 '17 at 11:06
  • basically I want a git command which will revert all the changes which is making the git status to show "red files" – Unbreakable Mar 26 '17 at 11:07
  • So I made a change to a file. I did not do anything else. NO git command at all (no git push not even git add or git commit). But now I want a git command which will revert those changes in my local repo. – Unbreakable Mar 26 '17 at 11:10
  • In a more technical terms "How to revert the file changes made in local repo which has not been put in the staging area" – Unbreakable Mar 26 '17 at 11:21
  • Didn't you try "git checkout file_name". Also, you can stash the changes by using "git stash". – Vidura Mudalige Mar 26 '17 at 12:14
  • Git reset without Head uses the current staged files. Use git reset head to specified a different commit. Like git reset Head~2 to go back to a previous commits. 2 is number of commits – ozkary Jul 30 '17 at 12:53
22

For a specific file:

  • git reset my_file.txt
  • git checkout my_file.txt

For all added files:

  • git reset .
  • git checkout .

Note: checkout changes the code in the files and moves to the last updated (committed) state. reset doesn't change the codes; it just resets the header.

Jonathan Leffler
  • 666,971
  • 126
  • 813
  • 1,185
Hasib Kamal
  • 1,971
  • 20
  • 26
  • 3
    Please explain the difference between `git reset ` and `git checkout `. – Trent Jan 22 '18 at 23:47
  • 1
    reset doesn't change the file, just put it away from the stage (=index, where it was put by git add) – franc Mar 12 '18 at 11:18
  • checkout change the codes in file and move to the last updated state. reset doesn't change the codes it just reset the header. As example, reset use for added or committed files resetting before push and checkout use for back to the last updated/committed stage before git add. – Hasib Kamal Mar 14 '18 at 11:38
  • 1
    reset = remove the file from stage however changes will still be there. checkout = gets the updated file from the repository and will overrides the current file – Imam Bux Sep 12 '18 at 10:16
19

To undo git add, use:

git reset filename
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Anirudh Sood
  • 1,380
  • 11
  • 6
17

There is also interactive mode:

git add -i

Choose option 3 to un add files. In my case I often want to add more than one file, and with interactive mode you can use numbers like this to add files. This will take all but 4: 1, 2, 3, and 5

To choose a sequence, just type 1-5 to take all from 1 to 5.

Git staging files

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Jonathan
  • 269
  • 3
  • 9
  • *"I'm surprised that no one mention interactive mode"* - they did: http://stackoverflow.com/a/10209776/1709587 – Mark Amery Oct 30 '15 at 23:52
16

This command will unstash your changes:

git reset HEAD filename.txt

You can also use

git add -p 

to add parts of files.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
wallerjake
  • 3,809
  • 3
  • 24
  • 30
16

2019 update

As pointed out by others in related questions (see here, here, here, here, here, here, and here), you can now unstage a single file with:

git restore --staged <file>

and unstage all files (from the root of the repo) with:

git restore --staged .

Notes

git restore was introduced in July 2019 and released in version 2.23.
With the --staged flag, it restores the content of the index (what is asked here).

When running git status with staged uncommitted file(s), this is now what Git suggests to use to unstage file(s) (instead of git reset HEAD <file> as it used to prior to v2.23).

prosoitos
  • 4,676
  • 5
  • 19
  • 35
15

git add myfile.txt # This will add your file into the to-be-committed list

Quite opposite to this command is,

git reset HEAD myfile.txt  # This will undo it.

so, you will be in the previous state. Specified will be again in untracked list (previous state).

It will reset your head with that specified file. so, if your head doesn't have it means, it will simply reset it.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Mohideen bin Mohammed
  • 14,471
  • 7
  • 86
  • 95
13
git reset filename.txt

Will remove a file named filename.txt from the current index, the "about to be committed" area, without changing anything else.

Rahul Sinha
  • 1,021
  • 9
  • 15
12

In Sourcetree you can do this easily via the GUI. You can check which command Sourcetree uses to unstage a file.

I created a new file and added it to Git. Then I unstaged it using the Sourcetree GUI. This is the result:

Unstaging files [08/12/15 10:43] git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree reset -q -- path/to/file/filename.java

Sourcetree uses reset to unstage new files.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
miva2
  • 1,955
  • 21
  • 30
  • 1
    Yes, the same technique can be used with [TortoiseGit](http://en.wikipedia.org/wiki/TortoiseGit), getting the Git commands for the common use cases. – Peter Mortensen Nov 03 '19 at 13:43
12
git reset filename.txt  

Will remove a file named filename.txt from the current index, the "about to be committed" area, without changing anything else.

Joseph Mathew
  • 961
  • 12
  • 16
10

One of the most intuitive solutions is using Sourcetree.

You can just drag and drop files from staged and unstaged

Enter image description here

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Marcin Szymczak
  • 9,665
  • 4
  • 48
  • 60
7

The git reset command helps you to modify either the staging area or the staging area and working tree. Git's ability to craft commits exactly like you want means that you sometimes need to undo changes to the changes you staged with git add.

You can do that by calling git reset HEAD <file to change>. You have two options to get rid of changes completely. git checkout HEAD <file(s) or path(s)> is a quick way to undo changes to your staging area and working tree.

Be careful with this command, however, because it removes all changes to your working tree. Git doesn't know about those changes since they've never been committed. There's no way to get those changes back once you run this command.

Another command at your disposal is git reset --hard. It is equally destructive to your working tree - any uncommitted changes or staged changes are lost after running it. Running git reset -hard HEAD does the same thing as git checkout HEAD. It just does not require a file or path to work.

You can use --soft with git reset. It resets the repository to the commit you specify and stages all of those changes. Any changes you have already staged are not affected, nor are the changes in your working tree.

Finally, you can use --mixed to reset the working tree without staging any changes. This also unstages any changes that are staged.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
SAIguru011
  • 466
  • 5
  • 13
5

You can unstage/undo using the git command or GUI git.

Single file

git reset File.txt 

Multiple files

git reset File1.txt File2.txt File3.txt

Example - Suppose you have added Home.js, ListItem.js, Update.js by mistake enter image description here and want to undo/reset =>

git reset src/components/home/Home.js src/components/listItem/ListItem.js src/components/update/Update.js

enter image description here

Same Example using git GUI

git gui

opens a window => Uncheck your files from Staged changes(Will Commit) enter image description here

akhtarvahid
  • 6,733
  • 2
  • 14
  • 21
  • If you decide to answer an older question that has well established and correct answers, adding a new answer late in the day may not get you any credit. If you have some distinctive new information, or you're convinced the other answers are all wrong, by all means add a new answer, but 'yet another answer' giving the same basic information a long time after the question was asked usually won't earn you much credit. You've added 'pretty pictures' — I'm not convinced they're all that beneficial. They'd be illegible if I was using a cell phone to read this answer. – Jonathan Leffler Sep 18 '20 at 17:32
3

You can using this command after git version 2.23 :

git restore --staged <filename>

Or, you can using this command:

git reset HEAD <filename>
  • Welcome to Stack Overflow. If you decide to answer an older question that has well established and correct answers, adding a new answer late in the day may not get you any credit. If you have some distinctive new information, or you're convinced the other answers are all wrong, by all means add a new answer, but 'yet another answer' giving the same basic information a long time after the question was asked usually won't earn you much credit. – Jonathan Leffler Oct 27 '20 at 05:48
2

The first time I had this problem, I found this post here and from the first answer I learned that I should just do git reset <filename>. It worked fine.

Eventually, I happened to have a few subfolders inside my main git folder. I found it easy to just do git add . to add all files inside the subfolders and then git reset the few files that I did not want to add.

Nowadays I have lots of files and subfolders. It is tedious to git reset one-by-one but still easier to just git add . first, then reset the few heavy/unwanted but useful files and folders.

I've found the following method (which is not recorded here or here) relatively easy. I hope it will be helpful:

Let's say that you have the following situation:

Folder/SubFolder1/file1.txt
Folder/SubFolder2/fig1.png
Folder/SubFolderX/fig.svg
Folder/SubFolder3/<manyfiles>
Folder/SubFolder4/<file1.py, file2.py, ..., file60.py, ...>

You want to add all folders and files but not fig1.png, and not SubFolderX, and not file60.py and the list keeps growing ...

First, make/create a bash shell script and give it a name. Say, git_add.sh:

Then add all the paths to all folders and files you want to git reset preceded by git reset -- . You can easily copy-paste the paths into the script git_add.sh as your list of files grows. The git_add.sh script should look like this:

#!/bin/bash

git add .
git reset -- Folder/SubFolder2/fig1.png
git reset -- Folder/SubFolderX
git reset -- Folder/SubFolder4/file60.py

#!/bin/bash is important. After this, you need to do chmod -x git_add.sh in the command line to make the script executable and then source git_add.sh to run it. After that, you can do git commit -m "some comment", and then git push -u origin master if you have already set up Bitbucket/Github.

Disclaimer: I've only tested this in Linux.


If you have lots of files and folders that you always retain in your local git repository but you don't want git to track changes when you do git add ., say video and data files, you must learn how to use .gitignore. Maybe from here.

Sam Macharia
  • 405
  • 5
  • 11
0

Use git reset HEAD to unstage everything you staged

Rubaiyat Jahan Mumu
  • 2,741
  • 1
  • 25
  • 32
  • 1
    If you decide to answer an older question that has well established and correct answers, adding a new answer late in the day may not get you any credit. If you have some distinctive new information, or you're convinced the other answers are all wrong, by all means add a new answer, but 'yet another answer' giving the same basic information a long time after the question was asked usually won't earn you much credit. – Jonathan Leffler Feb 19 '21 at 16:44
  • I was looking for this exact solution to unstage a bunch of files. I know it wont give me much credit but it will save someone's time. Thanks for the suggestion. I will keep that in mind. – Rubaiyat Jahan Mumu Feb 19 '21 at 17:12