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:
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 ) █