206

Is it possible to unstage the last staged (not committed) change in git? Suppose there were a lot of files in the current branch, some staged, some not. At some point, some foolish programmer accidentally executed:

git add -- .

...instead of:

git checkout -- .

Can this programmer now unstage his last changes with some magical git command? Or should he have committed before experimenting in the first place?

5
  • Heh. We got a useful question and answer out of this though.
    – steveha
    Commented May 16, 2015 at 2:58
  • 2
    possible duplicate of Undo 'git add' before commit
    – Jim Fell
    Commented Jun 26, 2015 at 15:11
  • I believe it is not the duplicate. OP in the other question is asking for a way to undo this or remove these files from the commit. I want(ed) precisely and only to undo the changes that were added with the last git add command, especially for the files that already had staged changes, and had some changes which were to be undone, not staged. Can't say the other question is not related though.
    – Septagram
    Commented Jun 30, 2015 at 9:08
  • 2
    Perhaps he should have /been/ committed before experimenting in the first place. Commented Jul 20, 2015 at 10:31
  • @android.weasel yes, that was many years ago...
    – Septagram
    Commented Jul 21, 2015 at 10:36

11 Answers 11

312

You can use git reset. This will 'unstage' all the files you've added after your last commit.

If you want to unstage only some files, use git reset -- <file 1> <file 2> <file n>.

Also it's possible to unstage some of the changes in files by using git reset -p.

3
  • 3
    How sad. I guess there's something wrong in my committing practices after all. Accepting this answer, because you mentioned -p switch. Thanks! :)
    – Septagram
    Commented Aug 26, 2012 at 20:14
  • Generates (for me) the error: fatal: Failed to resolve 'HEAD' as a valid ref. I haven't committed anything yet (new repo) just done git add . and regretted it. I don't want to reset the entire add, just one directory. git reset -- dir/*.* generates the error above. Commented Jan 23, 2014 at 17:51
  • ... Ah, I see what is happening for me. I did not have anything for HEAD to point to yet and so git reset failed (because it operates on the HEAD). Commented Jan 23, 2014 at 18:04
45

You cannot undo the latest git add, but you can undo all adds since the last commit. git reset without a commit argument resets the index (unstages staged changes):

git reset
2
  • 3
    "You cannot undo the latest git add": Wow, this is surprising and potentially painful. Is there a definitive source for this? Also, is there a good reason it should be so? Thanks! Commented Jun 8, 2016 at 2:45
  • @AndrewMoylan: well, there's no automatic way to do so. You can always reset a single file, or use reset -p to unstage a specific hunk.
    – knittl
    Commented Jun 8, 2016 at 5:28
17

So the real answer to

Can this programmer now unstage his last changes with some magical git command?

is actually: No, you cannot unstage just the last git add.

That is if we interpret the question as in the following situation:

Initial file:

void foo() {

}

main() {
    foo();
}

First change followed by git add:

void foo(int bar) {
    print("$bar");
}

main() {
    foo(1337);
}

Second change followed by git add:

void foo(int bar, String baz) {
    print("$bar $baz");
}

main() {
    foo(1337, "h4x0r");
}

In this case, git reset -p will not help, since its smallest granularity is lines. git doesn't know that about the intermediate state of:

void foo(int bar) {
    print("$bar");
}

main() {
    foo(1337);
}

any more.

1
  • 2
    I plussed because as a new git user, that's a really important distinction that highlights what my friends describe as "having good checkin hygiene"... my personal experience - it was described as "carpooling" (bad!).
    – benc
    Commented Mar 12, 2018 at 16:03
6

You could use git reset (see docs)

5

You can use

git reset

to undo the recently added local files

 git reset file_name

to undo the changes for a specific file

3

At date git prompts:

  1. use "git rm --cached <file>..." to unstage if files were not in the repo. It unstages the files keeping them there.
  2. use "git reset HEAD <file>..." to unstage if the files were in the repo, and you are adding them as modified. It keeps the files as they are, and unstages them.

At my knowledge you cannot undo the git add -- but you can unstage a list of files as mentioned above.

3

If you want to remove all added files from git for commit

git reset

If you want to remove an individual file

git rm <file>
2
  • 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:

    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>
    
0
0

Depending on size and scale of the difficultly, you could create a scratch (temporary) branch and commit the current work there.

Then switch to and checkout your original branch, and pick the appropriate files from the scratch commit.

At least you would have a permanent record of the current and previous states to work from (until you delete that scratch branch).

0

I would suggest to use:

git rm -r --cached <your_dir> or git rm --cached <your_file>

It reverts your

git add <your_dir_or_your_file>

back, while keeping the files as they are.

0

Just now, I was a little too quick on the Enter key, and accidentally added about 200 files in one directory to what I had already added (that was good). Here is what I did:

  1. git status > outputfile
  2. deleted all lines except the bad files that I didn't want
  3. used vi to change the beginning of each line to be git restore --staged<space>
  4. executed that file

problem solved.

Not the answer you're looking for? Browse other questions tagged or ask your own question.