views:

17041

answers:

16
+86  Q: 

Undo "git add"?

Git newbie here, quick question. I mistakenly added files using the command "git add file". I have not yet run "git commit". Is there a way to remove these files from the commit?

A: 

git remove / git rm can be used for this, with the --cached flag Try git help rm

gnud
+1 for the --cached thing, thanks ceretullis
dylanfm
+86  A: 

You can also git reset FILE, which will remove it from the current index (the "about to be committed" area) without changing anything else.

genehack
git reset HEAD _file_works for me
Sergey Kovalev
To undo `git add .` use `git reset`
takeshin
Nice alias for unstaging files: ` git config --global alias.unstage='reset HEAD --'`
takeshin
+27  A: 

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.

Paul Beckingham
Git is very helpful, I agree
dylanfm
Thanks for pointing this out! Somehow I always skipped those helpful tips that git was printing in front of my eyes.
tequilatango
+3  A: 

Please dont use "git remove / git rm". It will remove the file.

"git reset FILE" is the correct command.

+3  A: 

DO NOT USE "git rm" as suggested above, this is used to stop tracking a file and depending on the flags it may even remove it from your file system which is not what you want to do.

+107  A: 

Also a newbie I 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.

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 newbie 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 Stackoverflow - 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 .

UPDATE Oh yeah forgot to mention - 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)

Rhubarb
Hah, I just did exactly those things, right down to the search term! Cheers :)
Ben Hymers
Doesn't just "git reset" without . do what you want, or am I missing something?
ustun
+1 for the detailed answer.
Josh K
Great answer. +1 for using the `-n` option with `git add`. I'll definitely use that one.
Drew Noakes
Great answer. +1 for the running commentary.
Kelly French
Good stuff, what we all go through :)
Sam
+1 Haha! "undo git add". Thanks dude!
dty
Exactly what I needed! Thanks!
Arclite
A: 

I can confirm. git rm removes the file from the repository. Check out the example laid out below: We have an example repository in /tmp/foo and add three untracked files a, b, and c. Make an add to all all take it back with git rm --cached. Looks alright. Now we commit a to the rep. Now we make a slight change to a and also again accidentally do git add . in this scenario. And then use git rm --cached again. And we see that it also throws a out of the repository and marks it as deleted. Not exactly what you want.

mac:tmp neo$ mkdir foo

mac:tmp neo$ cd foo/

mac:foo neo$ git --version
git version 1.5.4.3

mac:foo neo$ git init
Initialized empty Git repository in .git/

mac:foo neo$ touch a
mac:foo neo$ touch b
mac:foo neo$ touch c

mac:foo neo$ git add  .

mac:foo neo$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file: a
#   new file: b
#   new file: c
#

mac:foo neo$ git rm --cached *
rm 'a'
rm 'b'
rm 'c'



mac:foo neo$ git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   a
#   b
#   c
nothing added to commit but untracked files present (use "git add" to track)

mac:foo neo$ git add a

mac:foo neo$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file: a
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   b
#   c
mac:foo neo$ git commit -m 'st.ov test'
Created initial commit 68867dc: st.ov test
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a

mac:foo neo$ git add .

mac:foo neo$ echo 'foo' > a
mac:foo neo$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   b
#   new file:   c
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#   modified:   a
#

mac:foo neo$ git rm --cached *
rm 'a'
rm 'b'
rm 'c'
mac:foo neo$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   deleted:    a
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   a
#   b
#   c
+1  A: 

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
A: 

Same problem here, git reset --HARD resets the head to the last commit but not undoes the uncommited add or remove.

git reset FILE gives me: fatal: Needed a single revision

The question is how to undo a not commited add, seems like reset is not the solution. Correct me if I am wrong.

`git reset HEAD filename` works for me.
Drew Noakes
A: 

As this is your first commit, you can run this instead:

rm -fr .git

And start again from scratch! (this is not the first time I'm, going through this cycle of init, add, commit, sh!t, google add undo, oh, why not remove the repository and start again)

:)

Brian Silberbauer
+1  A: 

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.

Kokotte23
+3  A: 

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

Paul Betts
One tip is to copy your .git/config file if you have added remote origin, before deleting the folder.
Tiago
There is no reason to throw away the whole index if it already has (otherwise) carefully selected content. Just do what `git status` says to do: `git rm --cached <file>`.
Chris Johnsen
+3  A: 

git rm --cached . -r

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

Stephen Braitsch
I wasn't looking to un-add everything, just ONE specific file.
ceretullis
A: 

Just type "git reset" and it is like you never typed "git add ." since your last commit.

Donovan
+7  A: 

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 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
takeshin
+1 for the suggested alias.
ceretullis
+2  A: 

As per many of the answers above you can git reset BUT, I found this great little post that actually adds the git command (well an alias) for "git unadd"

http://pivotallabs.com/users/alex/blog/articles/1001-git-unadd

Simply,

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

now you can

git unadd foo.txt bar.txt
electblake