git-版本回滚git reset --soft、--mixed、--hard
1、场景需求
某开发团队的A同学,工作积极性很高,已进入公司就开始进入工作状态,一天内就提交了很8次代码,但是当下午在和开发组长汇报工作的时候,发现在第4次提交代码后,由于业务需求不明,导致后续4次的提交都是有问题的。 这个时候,A同学就遇到了一个问题,我想要将已经提交过的多次记录给取消掉。 像这种多次commit取消的效果,其实有个专业术语,叫"版本回滚",版本回滚主要说的是对于已经提交的动作,进行撤销的动作,由于该动作涉及到的对象是仓库,在这里我们可以基于git reset命令来完成我们的目标。
2、reset原理
2.1、流程图
2.2、原理说明
git reset的提交流程可以理解为多次git rm。
reset执行前: A版本经过commit +b.txt 后到达B版本,在经过commit +c.txt 后到达C版本
reset执行后: C版本经过rm -c.txt 和 -b.txt后到达A版本
注意: 通过图示,可以看出来git reset有强制更新代码或者删除分支权限git reset会将commit记录删除掉
3、git reset命令解析
3.1、命令格式
命令格式:git help reset git reset [-q] [<tree-ish>] [--] <paths>... git reset (--patch | -p) [<tree-sh>] [--] [<paths>...] git reset [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit_id>]
该命令是对本地仓库的项目进行回滚操作的命令,它主要有如下几个参数 --soft # 缓存区和工作目录都不会被改变,只是本地库中的文件回滚到当时的那个版本 --mixed # 默认选项。缓存区和你指定的提交同步(被清空),但工作目录不受影响 --hard # 缓存区和工作目录都同步到你指定的提交,该选项非常危险
注意:这三个参数的区别点就是:我修改的内容需不需要保留的问题,作用范围如下
3.2、--soft、--mixed、--hard作用域图
4、--soft、--mixed、--hard-实践
4.1、准备环境
# 我们基于一个空的仓库,创建一个存在多次commit的效果: A-->B-->C mkdir /data/reset -p && cd /data/reset git init echo first >a.txt;git add a.txt;git commit -m "A" echo second >b.txt;git add b.txt;git commit -m "B" echo second >c.txt;git add c.txt;git commit -m "C"
4.2、--hard-实践
# --hard是一种代码仓库完整回滚的一种效果,能力还是相当的强。 # 缓存区和工作目录都同步到你指定的提交,该选项非常危险 # 当前效果示例 root@localhost:/data/reset# git log --pretty=format:"%h - %an, %ar : %s" --graph * 1b42d7c - 277667028@qq.com, 4 minutes ago : C * 222eb7c - 277667028@qq.com, 4 minutes ago : B * bd39d33 - 277667028@qq.com, 4 minutes ago : A # 向工作目录和暂存区中都增加一些内容 echo 'reset' > reset.txt git add reset.txt echo 'reset1' > reset1.txt git status # --hard 回滚到版本号为B git reset --hard 222eb7c git status root@localhost:/data/reset# ll drwxr-xr-x 8 root root 4096 Jun 11 04:04 .git/ -rw-r--r-- 1 root root 6 Jun 11 03:57 a.txt -rw-r--r-- 1 root root 7 Jun 11 03:58 b.txt -rw-r--r-- 1 root root 7 Jun 11 04:03 reset1.txt root@localhost:/data/reset# git status On branch master Untracked files: (use "git add <file>..." to include in what will be committed) reset1.txt nothing added to commit but untracked files present (use "git add" to track) #可以看到:除了未加入到git代码管理系统的文件,其他(工作目录、暂存区、本地仓库)都回滚到了B版本的效果,但是未被跟踪的文件是不会被管理起来的
4.3、--soft-实践
# --soft参数它只是将本地库中的文件回滚,其他两个位置不受影响 # 在版本B的基础上,给工作目录和暂存区增加一些文件 git add reset1.txt echo 'reset' > reset.txt git status # --soft回滚到版本号为A git reset --soft bd39d33 # git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: b.txt new file: reset1.txt Untracked files: (use "git add <file>..." to include in what will be committed) reset.txt # ll drwxr-xr-x 8 root root 4096 Jun 11 04:08 .git/ -rw-r--r-- 1 root root 6 Jun 11 03:57 a.txt -rw-r--r-- 1 root root 7 Jun 11 03:58 b.txt -rw-r--r-- 1 root root 6 Jun 11 04:08 reset.txt -rw-r--r-- 1 root root 7 Jun 11 04:03 reset1.txt # 可以看到:除了本地仓库中B的文件被退回到暂存区之外,其他都没有任何变化,即只有代码仓库文件被回滚了
4.4、--mixed-实践
# --mixed参数是默认选项。缓存区和你指定的提交同步(被清空),但工作目录不受影响 #在--soft实践的基础上,重新提交一次,并给暂存区增加一个文件 git add . git commit -m "D" echo d > d.txt git add d.txt git status # 查看当前提交状况 # git log --pretty=format:"%h - %an, %ar : %s" --graph * 9af9d00 - 277667028@qq.com, 12 seconds ago : D * bd39d33 - 277667028@qq.com, 14 minutes ago : A # --mixed 回滚到版本号为A git reset --mixed bd39d33 # ll drwxr-xr-x 8 root root 4096 Jun 11 04:11 .git/ -rw-r--r-- 1 root root 6 Jun 11 03:57 a.txt -rw-r--r-- 1 root root 7 Jun 11 03:58 b.txt -rw-r--r-- 1 root root 2 Jun 11 04:10 d.txt -rw-r--r-- 1 root root 6 Jun 11 04:08 reset.txt -rw-r--r-- 1 root root 7 Jun 11 04:03 reset1.txt # git status On branch master Untracked files: (use "git add <file>..." to include in what will be committed) b.txt d.txt reset.txt reset1.txt nothing added to commit but untracked files present (use "git add" to track) # 可以看到:D版本提交的内容和当时暂存区的内容,统统都发生了回滚,都变成了未跟踪状态了