本节按使用场景来总结说明,总结文件未提交前的常见回退情形
1. 新建文件暂存后撤销
在项目目录下新建version.md文件,将文件暂存,状态如下:
可以看到version.md是new file的状态。通过命令行的输出,我们知道可以使用
git reset HEAD
+ 文件名来撤销刚才的暂存:
OK,这样回到了我们暂存version.md之前的状态
2. 已提交过的文件的回退
已提交过的文件是指,该文件已进行过
git commit
操作,或者说该文件包含在一次commit之中,而不是new file状态
修改list.md文件,此时不暂存文件,
先使用git status
查看状态如下:
命令行输出告诉我们,可以使用git checkout --
文件名 来放弃刚才的修改,执行命令如下:
回到编辑器,可以看到刚才修改的内容已撤销了:
接下来,我们继续修改list.md文件,然后紧接着暂存。此时可使用git reset HEAD
+ 文件名让文件回到未暂存时的状态:
执行git reset HEAD list.md
后,可以看到文件状态从已暂存转换到了未暂存
(黄色—>红色):
之后,我们可以继续修改,或者使用刚刚说过的checkout命令来放弃更改了。
总结:
git reset HEAD
用来撤销暂存,git checkout
用来撤销修改,如果文件修改后已暂存,需要先撤销暂存,再撤销修改,一步步的来。
3. 未commit过的目录撤回的小疑问
对于一个尚未进行过任何提交的目录,已暂存文件的撤回,和1中描述的有所不同
新建一个blank工程,git init初始化完成,在其中新建1.md文件,暂存,查看文件状态:
这次让我们使用git rm
命令来取消暂存了
回想到,1小节中提示的命令是git reset HEAD
,那如果此时我们仍然使用git reset
是否可以呢?
提示我们HEAD是有歧义的,让我们使用 – 来隔开文件名,执行如下。
原来效果和使用rm命令是一样的。
但是为什么之前reset时直接后跟文件名,不需要使用 – 呢?这里推测应该是和工作目录未发生过commit有关,说明commit至少会改变HEAD的状态,因为没有提交,所以HEAD的指向不定?有待研究。。。。
4. 文件的移除
1、直接手动删除文件并提交
删除工程目录下的version.md文件,git status 查看:
可以看到,直接删除文件,相当于对文件做了一次修改,此时通过暂存 + 提交可以生效,通过checkout可以回退。
2、通过git rm 命令删除
使用git rm 命令,有两种方式:
-
使用 --cached 参数,仅从index移除,保留文件,执行后,文件仍会存在于工作目录下,commit后,version.md仍会留存在工作目录(可以叫做软删除)
此时,提示中的两种操作,都可以撤回移除动作,将version.md 回到“未修改”状态。 -
使用-f 参数,强制删除,执行后,文件会从工作目录移除,相当于手动删除文件 + 执行git add两步操作
此时,直接commit可以提交生效,通过reset HEAD -> checkeout,则可以撤回。
5、暂存后又添加了内容
如果我们暂存后,又改了文件内容了,此时的回退,文件状态应该怎么变动?
我们先修改version.md文件,添加一行内容,并暂存
此时不提交,继续在version.md添加一行内容:
查看文件状态,发现此时既是version.md已暂存状态,又是已修改状态。
此时回退,有以下两种情况:
- 执行git checkout – version.md,会撤销最近一次的修改,使文件恢复到最近的暂存状态,也就是说,version 2 这一行会被撤销!version 1则会被保留,仍是已暂存状态。
- 执行git reset HEAD version.md,会撤销最近的暂存,也就是说,version 1这一行会被撤销暂存,同时会和version 2 这一行,一起变为已修改的部分。看图:
如果已熟悉暂存和修改的,上面说的应该很好理解吧。
总结:在文件提交更改之前,会处于“已修改” 或 “已暂存” 的状态下,需要准确了解当前文件的状态,方能准确的处理回退的动作。
文件已提交过了,如何回退?甚至我想回退到之前的某一次的状态,该怎么办呢?下篇继续。