git中有很几个关于代码回退的命令:restore 、reset、revert ,初学git的同学们可能搞不清楚什么时候该用哪个,根据我的一点点经验,简单介绍一下它们,希望能帮到大家
(我的水平有限,内容仅供参考.,哪里有问题,欢迎指出)
将不在暂存区的文件撤销更改
将提交到暂存区的文件恢复到工作区
例1:将新增文件从暂存区到工作区(绿色变红),针对的是add操作
//创建a.txt
touch a.txt 红色
//编辑a.txt
echo "aaa" >> a.txt 红色
//将文件添加到暂存区
git add a.txt 绿色
//如何将a.txt 退回到工作区呢?
git restore --staged a.txt 变红色了
注意!已经在本地仓库的文件,用git restore --staged 命令无论如何也恢复不到工作区(变红),因为restore只针对暂存区
例2:旧文件在暂存区的修改,但没有add
旧文件 a.txt 灰白色
//编辑a.txt
echo "aaa" >> a.txt 蓝色
//如果将暂存区文件,在工作区的更改恢复到以前
git restore a.txt
当我们进行了错误的提交,但是还没有push到远程分支,想要撤销本次提交,建议使用git reset 命令
git reset 有三个参数
reset --hard 会在重置 HEAD 和branch的同时,重置stage区和工作目录里的内容。
你的stage区和工作目录里的内容会被完全重置为和HEAD的新位置相同的内容。换句话说,就是期间的所有修改会被全部擦掉。
reset --soft 会在重置 HEAD 和 branch 时,保留工作目录和暂存区中的内容,并把重置 HEAD 所带来的新的差异放进暂存区。
reset 如果不加参数,那么默认使用 --mixed 参数。
它的行为是:保留工作目录,并且清空暂存区。也就是说,工作目录的修改、暂存区的内容以及由 reset 所导致的新的文件差异,都会被放进工作目录。简而言之,就是「把所有差异都混合(mixed)放在工作目录中」
补充!!!
//git reset --hard HEAD 表示当前commit,作用也是工作区(删除)、暂存区(删除)、本地仓库(回滚)这种,和指向其它commit没什么区别
//一般用这个命令,将写了半天的代码恢复到没写之前~.~,有没有发现和IDEA中的Rollback很像呢?
//没错Rollback的原理就是:git reset --hard HEAD
git reset --hard HEAD
其它方面和revert的HEAD一样
#提交记录
A1 ---> A2 ---> A3 ---> A4 ---> A5 ---> A6(最新版本)
#对应的HEAD值,一般HEAD指向最新的一条A6
5 ---> 4 ---> 3 ---> 2 ---> 1 ---> 0(最新版本)
例1 撤销一次提交
旧文件 a.txt 灰白色
//编辑a.txt
echo "hard" >> a.txt 蓝色
//提交更改到暂存区
git add a.txt 蓝色
//提交更改到本地仓库
git commit -m "hard测试" 灰白色
//查看提交日志
git log --oneline
结果类似如下:
$ git log --oneline
bc9abf9 (HEAD -> master) ss
6151ecf (origin/master) fix:origin2的修改
220c79d ceshi3
4cd4ece ceshi2
其中bc9abf9 、6151ecf … 就是commit Id的简短版本,够用了
//如何撤销上一次的提交呢,使用 reset --hard 之前的commitId
reset --hard 6151ecf
//就发现上一次提交消失了,并且本地暂存区的代码,工作区的代码全部都恢复到之前的commitId版本了
如果我们想保留暂存区的代码
//假如在git commit -m "hard测试" 后
//编辑了a.txt,但不add到暂存区
echo "test" >> a.txt
//如果我们想保留工作区的代码更新
//可以使用 reset --soft 6151ecf 或者 reset --mixed 6151ecf
//它俩的区别是mixed会将暂存区的修改恢复到工作区(恢复到add之前的状态,可以参考git restore --staged 理解),而soft不会
总结:
三种模式都会撤销commit的提交,也就是本地仓库会回滚
soft 工作区(保留)、暂存区(保留)、本地仓库(回滚)
mixed 工作区(保留)、并将暂存区退回到工作区(不是删除,只是需要重新add)、本地仓库(回滚)所以也叫混合模式
hard 工作区(删除)、暂存区(删除)、本地仓库(回滚)
1、revert的原理是,在当前提交后面,新增一次提交,抵消掉上一次提交导致的所有变化。它不会改变过去的历史,所以是首选方式,没有任何丢失代码的风险
2、revert可以抵消上一个提交,那么如果想要抵消多个需要执行 git revert 倒数第一个commit id 倒数第二个commit
3、这个就常用于当你提交了一次commit之后发现提交的可能有问题就可以用到revert
4、还有一种情景是已经有很多人提交过代码,但是想改之前的某一次commit记录又不想影响后面的也可以使用revert,他会把你后面提交的记录都放到工作区只是合并的时候需要注意一点
如果commit后push到远程分支上了,建议用git revert
revert有两种方式:
#对commitId执行反向操作,恢复到commitId的上一个commitId的代码
git revert [commitId]
#提交记录
A1 ---> A2 ---> A3 ---> A4 ---> A5 ---> A6(最新版本)
#对应的HEAD值,一般HEAD指向最新的一条A6
5 ---> 4 ---> 3 ---> 2 ---> 1 ---> 0(最新版本)
#HEAD相当于HEAD~0 表示对最近的一次提交(A6)实施反向操作,也就是将代码变成A5的版本
#相当于 git revert HEAD~0 相当于 git revert A6
git revert HEAD
#git revert HEAD~1 表示git revert A5,也就是将代码变成A4的版本
git revert HEAD~1
#如果要回到A3,那么就要生成A4,A5,A6相反的提交,这里可以用范围( ] 前开后闭
git revert HEAD~3..HEAD
注意!
1.执行 git revert HEAD 后会自动commit,并进入vim界面,让你填写commit 消息
#如果生成了反向操作,但暂时不想自动提交可以用--no-commit
git revert --no-commit HEAD
2.如果我们跳过HEAD~ HEAD~1和HEAD~2,直接执行git revert HEAD~3 ,会出现和HEAD~ HEAD~1和HEAD~2的冲突
解决方式一就是:一次生成多个反向操作
git revert HEAD~3..HEAD
解决方式二就是:自己解决冲突咯,然后再add .,commit,push
//我个人喜欢第二种(懒),但是我推荐你用第一种(生成多个反向的commit,很清晰)
例1 如果生成相反的提交操作
//创建文件 a.txt
touch a.txt
//开始第一次
echo "1" >> a.txt
git add .
git commit -m "feat:1"
//开始第二次编辑
echo "2" >> a.txt
git add .
git commit -m "fix:2"
//开始第三次编辑
echo "3" >> a.txt
git add .
git commit -m "fix:3"
//开始第四次编辑
echo "4" >> a.txt
git add .
git commit -m "fix:4"
//开始第五次编辑
echo "5" >> a.txt
git add .
git commit -m "fix:5"
//五次差不多了,push
git push
查看下日志
//--oneline :日志简略版
//-5 :只展示最近5条
$ git log --oneline -5
1e4c0e3 (HEAD -> master, origin/master) fix:5
ba8edff fix:4
742997a fix:3
a668a6f fix:2
e8ffae4 fix:1
如果我们想恢复到fix:3的代码,那么就需要对fix:5和fix:4做revert
//生成多个反向commit,不需要解决冲突
git revert HEAD~2..HEAD
//生成一个反向commit,需要解决冲突
git revert HEAD~1
1e4c0e3 (HEAD -> master, origin/master) fix:5
ba8edff fix:4
742997a fix:3
a668a6f fix:2
e8ffae4 fix:1
如果我们想恢复到fix:3的代码,那么就需要对fix:5和fix:4做revert
//生成多个反向commit,不需要解决冲突
git revert HEAD~2..HEAD
//生成一个反向commit,需要解决冲突
git revert HEAD~1