How to undo a git add?

How to remove a file from the staging area?

You have added a file to the staging area with git add, but you have not pushed your change to the remote repository. You can easily undo that change.

Setup

Let’s first create a file and commit it.

alina

alina git:( main ) echo "my content" > file.txt

alina git:( main ) git add file.txt

alina git:( main ) git commit -m 'add file.txt'

[main da60e4e] add file.txt

 1 file changed, 1 insertion(+)

 create mode 100644 file.txt

alina git:( main )

This created a new commit with a file called file.txt and a Git graph that looks like this:

alina

da60e4ea69d85fmainHEAD

We also have a clean Git status.

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 1 commit.

  (use "git push" to publish your local commits)

nothing to commit, working tree clean

alina git:( main )

Now, let’s update that file and add it to the staging area.

alina

alina git:( main ) echo "extra content" >> file.txt

alina git:( main ) git add file.txt

alina git:( main )

But this time, we realize that we don’t want this change to be part of the next commit. How can we undo it?

Solution

The good news is that the git status command tells you exactly what to do:

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 1 commit.

  (use "git push" to publish your local commits)

Changes to be committed:

  (use "git restore --staged <file>..." to unstage)

        modified:   file.txt

alina git:( main )

The git restore --staged <file>... command will unstage the file, which is exactly what we want.

alina

alina git:( main ) git restore --staged file.txt

alina git:( main )

Running git status again will confirm that the file is no longer staged.

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 1 commit.

  (use "git push" to publish your local commits)

Changes not staged for commit:

  (use "git add <file>..." to update what will be committed)

  (use "git restore <file>..." to discard changes in working directory)

        modified:   file.txt

no changes added to commit (use "git add" and/or "git commit -a")

alina git:( main )

There are other ways to achieve the same result, but this is the simplest one. Let’s explore the other options in the next section.

Other solutions

git reset HEAD file…

First, let’s re-add the file to the staging area.

alina

alina git:( main ) git add file.txt

alina git:( main )

Older versions of Git may suggest using the git reset HEAD <file>... command.

alina

alina git:( main ) git reset HEAD -- file.txt

Unstaged changes after reset:

M       file.txt

alina git:( main )

The git status command confirms that the file is no longer staged.

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 1 commit.

  (use "git push" to publish your local commits)

Changes not staged for commit:

  (use "git add <file>..." to update what will be committed)

  (use "git restore <file>..." to discard changes in working directory)

        modified:   file.txt

no changes added to commit (use "git add" and/or "git commit -a")

alina git:( main )

git rm —cached file…

First, let’s re-add the file to the staging area.

alina

alina git:( main ) git add file.txt

alina git:( main )

The git rm --cached <file>... command will also unstage the file.

alina

alina git:( main ) git rm --cached file.txt

rm 'file.txt'

alina git:( main )

The git status command confirms that the file is no longer staged.

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 1 commit.

  (use "git push" to publish your local commits)

Changes to be committed:

  (use "git restore --staged <file>..." to unstage)

        deleted:    file.txt

Untracked files:

  (use "git add <file>..." to include in what will be committed)

        file.txt

alina git:( main )

git reset -p

A more complex use case would be if you want to remove only parts of the file from the staging area. Let’s start by adding a new line to the file:

alina

alina git:( main ) echo "yet another extra content" >> file.txt

alina git:( main )

The content of this file is now:

alina

alina git:( main ) cat file.txt

my content

extra content

yet another extra content

alina git:( main )

And you add it again to the staging area.

alina

alina git:( main ) git add file.txt

alina git:( main )

The git status command confirms that the file is staged.

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 1 commit.

  (use "git push" to publish your local commits)

Changes to be committed:

  (use "git restore --staged <file>..." to unstage)

        modified:   file.txt

alina git:( main )

The git reset -p command will allow you to unstage only parts of the file.

alina

alina git:( main ) git reset -p file.txt

diff --git a/file.txt b/file.txt

index 025d08b..d8d1adb 100644

--- a/file.txt

+++ b/file.txt

@@ -1 +1,3 @@

 my content

+extra content

+yet another extra content

(1/1) Unstage this hunk [y,n,q,a,d,e,?]? ?

alina git:( main )

The output of that command may seem a bit confusing at first. The easiest way to get more information is to type e: A text editor opens up with more detailed instructions.

# Manual hunk edit mode -- see bottom for a quick guide.

@@ -1 +1,3 @@

 my content

+extra content

+yet another extra content

# ---

# To remove '+' lines, make them ' ' lines (context).

# To remove '-' lines, delete them.

# Lines starting with # will be removed.

# If the patch applies cleanly, the edited hunk will immediately be marked for unstaging.

# If it does not apply cleanly, you will be given an opportunity to

# edit again.  If all lines of the hunk are removed, then the edit is

# aborted and the hunk is left unchanged.

The instructions are pretty clear: to remove the lines that you don’t want to stage, you need to replace the + with a space. So, if you replace the line:

+extra content

with:

 extra content

When you save the editor, Git will unstage that line. The git status will now show that the file is partially staged.

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 1 commit.

  (use "git push" to publish your local commits)

Changes to be committed:

  (use "git restore --staged <file>..." to unstage)

        modified:   file.txt

Changes not staged for commit:

  (use "git add <file>..." to update what will be committed)

  (use "git restore <file>..." to discard changes in working directory)

        modified:   file.txt

alina git:( main )

Some parts of the file are staged, and some are not. Your local copy of the file is still the same.

alina

alina git:( main ) cat file.txt

my content

extra content

yet another extra content

alina git:( main )

The git diff --staged command will show you the changes that are currently staged.

alina

alina git:( main ) git diff --staged

diff --git a/file.txt b/file.txt

index 025d08b..f3db828 100644

--- a/file.txt

+++ b/file.txt

@@ -1 +1,2 @@

 my content

+extra content

alina git:( main )

You can see that only the line extra content is staged. You can now commit the changes.

alina

alina git:( main ) git commit -m 'update content'

[main c60b7b1] update content

 1 file changed, 1 insertion(+)

alina git:( main )

The git status shows that you still have changes in the file that are not staged.

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 2 commits.

  (use "git push" to publish your local commits)

Changes not staged for commit:

  (use "git add <file>..." to update what will be committed)

  (use "git restore <file>..." to discard changes in working directory)

        modified:   file.txt

no changes added to commit (use "git add" and/or "git commit -a")

alina git:( main )

The git diff command will show the changes that are not staged.

alina

alina git:( main ) git diff

diff --git a/file.txt b/file.txt

index f3db828..d8d1adb 100644

--- a/file.txt

+++ b/file.txt

@@ -1,2 +1,3 @@

 my content

 extra content

+yet another extra content

alina git:( main )

You can now stage the changes and commit them.

alina

alina git:( main ) git add file.txt

alina git:( main ) git commit -m 'and another update'

[main d2591f7] and another update

 1 file changed, 1 insertion(+)

alina git:( main )

And now your staging area and your local copy of the file are in sync.

alina

alina git:( main ) git status

On branch main

Your branch is ahead of 'origin/main' by 3 commits.

  (use "git push" to publish your local commits)

nothing to commit, working tree clean

alina git:( main )