【学了就忘】Git操作 — 26.撤销操作(二)
3、撤销暂存区中文件的修改
如果已经把修改的个文件添加到暂存区,可以用下面的命令撤销。
还是以上面test.txt文件为例。
1)修改test.txt文件并存储到暂存区
# 1.修改文件
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git status
On branch master
nothing to commit, working tree clean
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ echo "hello git v4" >> test.txt
# 2.添加文件到暂存区
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git add test.txt
warning: LF will be replaced by CRLF in test.txt.
The file will have its original line endings in your working directory
# 3.查看工作目录中文件状态
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
说明:
-
Changes to be committed::表示暂存区中所做的更改如下,可以提交。 -
git restore --staged <file>...:该命令表示取消暂存,把暂存区中的文件撤回到工作区。
Tips:
老版本Git会提示:(use "git reset HEAD <file>..." to unstage)
新版本Git会提示:(use "git restore --staged <file>..." to unstage)
和上面同理:
- 早期的Git中
git checkout命令承载了分支操作和文件恢复的部分功能,有点复杂,并且难以使用和学习,所以社区解决将这两部分功能拆分开,Git 2.23.0版本中中引入了两个新的命令git switch和git restore。 - 早期的Git中,文件恢复涉及到两个命令,一个是
git checkout命令,一个是git reset命令。git reset命令除了重置分支之外,还提供了恢复文件的能力。 - 而新的
git restore命令,代替了checkout命令和reset命令(但是这两个命令还可以进行文件恢复),专门用来恢复暂存区和工作区的文件。
2)撤销暂存区中test.txt文件的修改
[1]使用git restore --staged命令撤销暂存区中文件的修改。
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git restore --staged test.txt
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git status
On branch master
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: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
(重点)我们可以看到,test.txt文件从暂存区中撤销到工作区中,但是不会撤销工作区中文件的更改。
[2]使用git restore命令,不带--staged参数,撤销暂存区中文件的修改。
# 1.文件添加到暂存区中
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git add test.txt
warning: LF will be replaced by CRLF in test.txt.
The file will have its original line endings in your working directory
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
# 2.使用`git restore`命令,撤销暂存区中文件的修改
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git restore test.txt
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
我们可以看到,工作目录中test.txt文件状态没有改变,所以要撤销暂存区中文件的修改,必须加上--staged参数。
这是为什么呢?(个人理解)
因为git restore命令,不带--staged参数,背后的执行逻辑是,把暂存中的test.txt文件复制一份,覆盖掉工作区的test.txt文件,但是这样就形成了test.txt文件在工作区和暂存区一样的状态,所以工作区和暂存区的状态也一样。这也就是上面执行完git restore test.txt命令,在工作目录test.txt文件的状态,没有变化的原因。
[3]使用git reset HEAD <file>...命令撤销暂存区中文件的修改。
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git reset HEAD test.txt
Unstaged changes after reset: # 表示重置后文件未被跟踪
M test.txt # M:应该是modified的意思吧
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/learngit (master)
$ git status
On branch master
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: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
我们看到git reset HEAD <file>...命令的执行效果和git restore --staged命令执行的效果是一样的,这里就不多解释了。
之后要在进行撤销工作区中文件的修改,就和上一步一样了。
4、总结
前面通过详细的步骤,分别演示了从工作区和暂存区做撤销修改的操作。
下面我们总结一下,方便我们对前面知识的理解。
-
git checkout命令,既可以用来切换分支,又可以用来恢复工作区文件。恢复文件命令:
git checkout -- 文件 -
git reset命令,除了能够重置分支之外,还提供了恢复文件的能力。恢复文件命令:
git reset HEAD 文件 -
Git 2.23.0版本中,提供了
git restore命令,代替了git checkout命令和git reset命令的恢复文件功能。(但上面两个命令也能恢复文件)修改的文件只在工作区,没有添加到暂存区中,使用
git restore 文件命令。修改的文件已经添加到暂存区,但还没有提交,使用
git restore --staged 文件命令。
在来详细说明一下git restore命令:
这里有两种情况:
一种是test.txt自修改后还没有被放到暂存区,现在的撤销修改就回到和版本库一模一样的状态;
一种是test.txt已经添加到暂存区后,又作了修改,现在的撤销修改就回到添加到暂存区后的状态。
而git restore --staged命令:
用于已经把修改的文件添加到暂存区,没有被修改,但还未提交。这时执行该命令,直接撤销暂存区总存储的修改,将文件恢复到工作区去。