How to revert a file to a specific commit
You made some changes to a file, but you want to revert that file to a specific commit. This is the only file you want to revert. You don't want to revert the entire repository.
Initial situation
Let’s say you are on a branch with multiple commits.
The git log
command displays the commit history.
alina
alina git:( main ) git log
commit 94e6fe54dd927e5ac654cf5dd851d26b0d7cb580 (HEAD -> main)
Author: alina <alina@email.com>
Date: Mon Jun 26 07:50:10 2023 -0700
add line 5
commit a8b2b1f48c144070d3095362843007af730dc9ec
Author: alina <alina@email.com>
Date: Mon Jun 26 07:50:06 2023 -0700
add line 4
commit 2b61754bf4c66dfc0401ae57c0b3f3a0db020173
:
Author: alina <alina@email.com>
Date: Mon Jun 26 07:50:01 2023 -0700
add line 3
commit bf51c6c13d763025aadc3091f248bb2d9c5cefb9
Author: alina <alina@email.com>
Date: Mon Jun 26 07:49:57 2023 -0700
add line 2
commit 4fa21452a43aaaf8509a9638b875a1db1503da24
Author: alina <alina@email.com>
:
Date: Mon Jun 26 07:49:53 2023 -0700
add line 1
commit 1da58fdd1e1ee0a686730f8b721b5204f15fac87 (origin/main, origin/HEAD)
Author: gitpowerup <gitpowerup@mail.com>
Date: Mon Jun 26 07:49:32 2023 -0700
Initial commit
alina git:( main ) █
You realize that you want to revert a single file to a specific commit:
you want the content of the file file.txt
to match that of the commit 2b61754
.
Your current file file.txt
has the following content:
alina
alina git:( main ) cat file.txt
1
2
3
4
5
alina git:( main ) █
and you want to revert it to the content of the file file.txt
in the commit 2b61754
(where the last 2 lines were not there).
First, you can do a diff to confirm that this is the commit you want to revert to.
alina
alina git:( main ) git diff 2b61754 -- file.txt
diff --git a/file.txt b/file.txt
index 01e79c3..8a1218a 100644
--- a/file.txt
+++ b/file.txt
@@ -1,3 +1,5 @@
1
2
3
+4
+5
alina git:( main ) █
When you use file name in a git command line, it is safer to use the double dash --
before the file name.
This is not required in this case, because the file name file.txt
is not ambiguous.
You have multiple ways to reset the file to the commit 2b61754
. These 2 commands differ in the way they affect your working directory.
option #1 : git reset
The git reset
command will revert the file to the state of the commit 2b61754
.
alina
alina git:( main ) git reset 2b61754 -- file.txt
Unstaged changes after reset:
M file.txt
alina git:( main ) █
If you check the content of the file file.txt
, you will see that it was not changed:
alina
alina git:( main ) cat file.txt
1
2
3
4
5
alina git:( main ) █
And the git status
shows that the file file.txt
is modified: the git reset
command did not change the file in your working directory,
but it did stage the file from the 2b61754
commit.
alina
alina git:( main ) git status
On branch main
Your branch is ahead of 'origin/main' by 5 commits.
(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 ) █
The git diff
command shows that the file file.txt
differs from the staging area:
alina
alina git:( main ) git diff
diff --git a/file.txt b/file.txt
index 01e79c3..8a1218a 100644
--- a/file.txt
+++ b/file.txt
@@ -1,3 +1,5 @@
1
2
3
+4
+5
alina git:( main ) █
and this is the same diff as the one between the staging area and your current HEAD
:
alina
alina git:( main ) git diff --staged
diff --git a/file.txt b/file.txt
index 8a1218a..01e79c3 100644
--- a/file.txt
+++ b/file.txt
@@ -1,5 +1,3 @@
1
2
3
-4
-5
alina git:( main ) █
So here you have 2 options:
- if you commit the file
file.txt
now, you will have the same content as the commit2b61754
, but you would still have to revert the changes in your local directory. - you can change your mind and
git add
the file to ignore the change you made.
option #2 : git restore
Let’s go back to our initial state.
alina
alina git:( main ) git reset --hard main
HEAD is now at 94e6fe5 add line 5
alina git:( main ) █
with our initial commit tree:
The git restore
command can be used to restore a file to a specific commit, and also update your working directory:
alina
alina git:( main ) git restore --source 2b61754 file.txt
alina git:( main ) █
Your working directory now contains the content of the file file.txt
from the commit 2b61754
:
alina
alina git:( main ) cat file.txt
1
2
3
alina git:( main ) █
but the staging area has not been updated:
alina
alina git:( main ) git status
On branch main
Your branch is ahead of 'origin/main' by 5 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 confirms this:
alina
alina git:( main ) git diff
diff --git a/file.txt b/file.txt
index 8a1218a..01e79c3 100644
--- a/file.txt
+++ b/file.txt
@@ -1,5 +1,3 @@
1
2
3
-4
-5
alina git:( main ) █
The git restore
command is available since git 2.23.0.
Before that the command to use would have been:git checkout 2b61754 -- file.txt
.