Git后悔药之回滚及撤销操作(图文详解)
Git后悔药之回滚及撤销操作(图文详解)
在使用Git进行版本控制时,难免会遇到需要撤销或回滚提交的情况。本文将详细介绍Git中的两个重要命令:reset和revert,帮助你更好地管理代码版本。
前言
在利用GIT实现多人合作程序开发的过程中,我们有时会出现错误提交的情况,此时我们希望能撤销提交操作,让程序回到提交前的样子,本文总结了两种解决方法.
reset:删除直到XXX版本的所有commit(回滚到指定版本)
revert:删除某个XXX版本的commit(删除已提交的某个版本)
git的版本管理,及HEAD的理解
使用git的每次提交,Git都会自动把它们串成一条时间线,这条时间线就是一个分支。如果没有新建分支,那么只有一条时间线,即只有一个分支,在Git里,这个分支叫主分支,即master分支。有一个HEAD指针指向当前分支(只有一个分支的情况下会指向master,而master是指向最新提交)。每个版本都会有自己的版本信息,如特有的版本号(用hash值表示)、版本名等。如下图,假设只有一个分支:
reset(回滚)
git reset [commit-id]
操作回退到对应的
commit-id
,它会完成把
commit-id
之前的所有的所有
commit
的记录按照对应的模式进行处理
注意(下面两段话要理解):
commit-id
默认就是当前最近的一条
commit-id
,此时
commit
的所有记录不会更改,只会更具明命令中的模式对当前工作区与暂存区的修改做对应的操作
commit-id
如果为非最近的一条
- 那么首先会把
commit-id
之后的所有的
commit
记录所有的改动都按照命令中的模式处理到暂存区与工作区
- 再去按照命令中的模式操作当前的暂存区和工作区的内同
主要命令参数解析
git reset [--hard | --soft | --mixed(默认值)] [HEAD(默认值) | commit-id | origin/远程分支 ] [path(默认值为全部文件)]
模式(默认为–mixed)
--hard
回退到指定版本,工作区内容删除,暂存区内容删除
--soft
回退到指定版本,工作区内容保留,暂存区内容保留
--mixed
回退到指定版本,工作区内容保留,暂存区内容回退到工作区
提交示例
下面实操,根目录分别创建test1\test2\test3依次提交三次
查看版本号
cmd查看
git log
git查看
sourceTree查看
回滚版本
使用git reset --mixed(默认)
例子中
test1.txt
的hash值为
3bfbf125d290e9fdc91233d2852219cf5ae6ac9b
使用命令行
git reset --mixed 3bfbf125d290e9fdc91233d2852219cf5ae6ac9b
git reset 3bfbf125d290e9fdc91233d2852219cf5ae6ac9b
使用idea界面操作
回退之后的test2.txt和test3.txt文件还存在,不过在工作区
使用git reset --soft
操作过程和mixed同理,这里不赘述,直接看结果
使用git reset --hard
使用hard之后,两个文件直接被删除了
这是三种回滚方式直观区别
更新远程仓库
远程git仓库依旧存在
由于本地代码和远程代码不相符 , HEAD指向的版本比远程库的要旧 , 用“git push”会报错,所以要强行提交 , 本地覆盖远程仓库“git push -f”.
查看仓库
已回滚到指定版本
revert(撤销)
git revert
是用于“反做”某一个版本,以达到撤销该版本的修改的目的。比如,我们commit了三个版本(test1、test2、test3),突然发现test2不行(如:有bug),想要撤销test2,但又不想影响撤销test3的提交,就可以用
git revert
命令来反做test2,生成新的test4,这个test4里会保留test3的东西,但撤销了test2的东西
适用场景:如果我们想撤销之前的某一版本,但是又想保留该目标版本后面的版本,记录下这整个版本变动流程,就可以用这种方法。
提交示例
下面实操,根目录分别创建test1\test2\test3依次提交三次
查看版本号
撤销版本
使用
git revert -n 版本号
撤销
或者使用idea操作
如果是命令行需要重新commit
git commit -m 版本名
撤销过后进行新版本提交 , 已查到最新提交.
可能会出现冲突 , 需要修改冲突的文件 , 而且要git add 文件名 , 加入本地仓库暂存区
更新远程仓库
查看仓库
更新成功 , "test2"已被撤销 , 其他被保留
最后
虽然reset和revert都可以作为Git中的“后悔药”,但它们之间还是有明显区别的。
功能上:reset是一个栈式操作,会一次性失去从HEAD到目标提交这个区间内的所有提交;而revert是针对某一单独版本的撤销,提供了更精确的控制。
历史修改:reset直接修改了Git历史,被重置的提交相当于直接消失了,无法在事后追溯,非常危险。而revert创建了新的提交,不会导致历史信息的丢失,就算改错了也能追根溯源,安全性更高!