git 版本回退操作git reset、git revert
回退分两种情况:1.已 commit,未push到远程仓库。git reset --soft(撤销commit)。git reset --mixed(撤销 commit 和 add 两个动作)。2.已 commit,并且push到了远程仓库。git reset --hard(撤销并舍弃版本号之后的提交记录)。git revert(撤销,但是保留了提交记录)。revert 合并提交有坑 reset
概括
本文 git 相关命令:
- git reset:回退版本,将之后的提交记录全部抹去,将 HEAD 指向自己重置的提交记录。git reset [--soft | --mixed | --hard] commitId。
- git revert:撤销某个提交,做反向操作,生成新的commitId,原有提交记录保留;撤回某一次提交记录,若之后又有提交,提交记录还存在。。git revert commitId。
- git status:查看文件在工作区和暂存区的状态。
- git log:查看代码提交记录。
- git cherry-pick:选择commitId 应用在当前分支。git cherry-pick commitId。
回退分两种情况:
- 已 commit,未push到远程仓库。
- 已 commit,并且push到了远程仓库。
一、已 commit,未push到远程仓库
1.1 git reset --soft(撤销commit)
touch 创建了一个a.text,并提交到了本地仓库。
此时回滚a.text,git log找到要回退到的版本号,此处版本号为前一个版本。(或者通过 git reset [HEAD] 回退版本)
执行命令:git reset --soft 7ee5305f1e1e0f66c7d69666ff7054fc6e309464
通过idea可看到commit 记录被撤销了。
1.2 git reset --mixed(撤销 commit 和 add 两个动作)
touch创建新文件 b.text, 并提交到本地仓库。
通过git log找到要回退到的版本号 7ee5305f1e1e0f66c7d69666ff7054fc6e309464
执行命令:git reset --mixed 7ee5305f1e1e0f66c7d69666ff7054fc6e309464
此时可以看到,git reset --mixed 撤销的文件 未加入到暂存区,所以是撤销 commit 和 add 两个动作。
二、已 commit,并且push到了远程仓库
2.1 git reset --hard(撤销并舍弃版本号之后的提交记录)
新建文件a.text,并push到远程
执行命令:
-
git reset --hard 7ee5305f1e1e0f66c7d69666ff7054fc6e309464
-
git push -f(强制推送到远程,之前提交都会被覆盖,慎用)
此时可用看到提交记录和文件都被撤销了。使用需谨慎,不推荐使用。
当然,如果不小心用了git reset --hard 操作回退了,那么可用git reflog命令查看命令历史,找到被删除的commit,再次操作。
2.2 git revert(撤销,但是保留了提交记录)推荐
有一天项目经理跟你说,你开发上线的代码有问题,需要马上撤回。
撤回?你第一反应那不就是 reset
一下嘛。
正当你满心欢喜,想找到需要reset 的commitId时,你惊喜的发现,master分支上已经有其他同同事提交的代码了。
怎么办?用reset的话 会把同事这部分代码也撤回了。
但此时情况又十分紧急,你绞尽脑汁也没有想到好的办法。只能任性的使用 reset。
然后低头哈腰的让同事把他们代码重新合一遍,从此你在你同事眼里就打上了菜鸡的标签。
git revert原理:
- 生成新的提交:git revert 会创建一个新的提交,内容是要撤销的提交的“反操作”。也就是说,git revert 会通过相反的改动来撤销指定提交的更改。例如,如果原来提交中增加了某些代码行,git revert会通过删除这些行来撤销该提交。
- 保持项目历史的完整性:与git reset可能修改项目历史不同,git revert不会删除任何提交,而是通过新的提交来记录撤销操作,从而保证了版本历史的完整性。这使得它特别适用于公共分支(如 master 或 main 分支)。
新建文件a.text,并push到远程。
通过 git revert 版本号,撤销当前提交记录。版本号为要撤销的版本号,此处为当前提交的版本号。
可以看到本地和远程仓库文件都被撤销了。但是git log中能看到提交和撤销记录。
推荐用这种方式回退远程的代码。比如我们在master分支提交错了文件需要回退,那么我们用这个方式回退后,再用git cherry-pick commitId 重放该提交。最后本地修改了再push到远程。
示例演示
我们通过示例来更好的理解 revert 命令
上面是最近的5次提交记录,这时第3提交有错误,需要撤回这次提交。
执行命令
git revert 6274264
在执行 git revert 后,会弹出默认编辑器来让你对该次变更的信息进行修改。
git revert -e / --edit commit-id
这是默认的选项,你不需要单独配置它,有了这个配置,在执行 git revert 后,会弹出默认编辑器来让你对该次变更的信息进行修改。git revert --no-edit commit-id
与 -e / --edit 相反,传入这个选项那么就不会弹出默认编辑器来让你修改变更信息。git revert -n / --no-commit commit-id
传入这个选项意味着 git revert 执行后并不会自动产生commit,而是把改动的代码加到工作区和暂存区,用户可以自行修改并提交commit。
因为 revert 会生成一条新的提交记录,这时会让你编辑提交信息,编辑完后 :wq
保存退出就好了。
保存之后,我们再来看当前提交的记录
通过提交历史日志我们可以发现 虽然是撤回提交3,但之前4和5的提交记录都还在,这点和reset 不一样。
说明 git revert 可以保留完整的 git 历史,对多人合作的分支来说比较友好。
同时我们也看下 1ccafe6
这次到底提交了什么内容
查看命令
git show 1ccafe6
我们可以看出,这次revert 仅仅撤回 第 3 次提交的内容。它采用逆向操作。如果之前有创建文件->删除文件,新增代码->删除代码,删除代码->新增代码等。
通过这样一种方式,来撤回具体某一次的操作。
git revert 是反做撤销其中的commit-id,然后重新生成一个commit-id。本身不会对其他任何的提交commit-id产生影响
revert 合并提交有坑
在 git 的 commit 记录里,还有一种类型是合并提交,想要 revert 合并提交,使用上会有些不一样。
现在 发现 3b5ad0c
合并分支提交有误,需要撤回。
1、坑一
我们用上面同样的命令
$ git revert 3b5ad0c
error: commit 3b5ad0cfcad49f7d2caa65449a8adf713da0accd is a merge but no -m option was given.
fatal: revert failed
使用刚刚同样的 revert 命令,会发现命令行报错了。
为什么会这样?
因为merge
操作有2个分支,而revert不知道要还原哪个分支的提交。需要使用-m 1
参数来告诉revert命令哪个是主线。
选择主线就还原非主线,选择非主线就还原主线。
修改命令
git revert -m 1 3b5ad0c
可以发现revert撤销成功了。
2、坑二
在上面的场景中,虽然撤销了master合并到feature这一次提交。
但如果你在切到master,再将修改后的代码提交。再次合并到feature分支时,会发现之前被 revert 的修改内容没有重新合并进来。
那是因为你在feature 虽然使用了 revert 命令。但当前分支还是会保留之前合并的记录,git 判断有相同的 commitHash,就忽略了相关 commit 修改的内容。
这时就需要 revert 掉之前 revert 的合并提交。
具体命令
- 83c20e0是之前撤销合并请求的commitId
git revert 83c20e0
这样之后,之前 通过revert 撤回的代码才不会丢失。
对于 revert 撤回 Merge 提交,你必须重新把Revert的再Revert回去,不然Git会认为你不需要这些内容。也就是说,下一次Merge的时候,会丢失代码!
reset 和 revert 区别
reset命令是重置
到一个记录:git reset是将之前的提交记录全部抹去,将 HEAD 指向自己重置的提交记录;
revert命令是撤回
一个记录;git revert 操作是撤回某一次提交记录,若之后又有提交,提交记录还存在。
三、总结
回退分两种情况:
1.已 commit,未push到远程仓库。
- git reset --soft [commitId](撤销commit)。
- git reset --mixed [commitId](撤销 commit 和 add 两个动作)。
2.已 commit,并且push到了远程仓库。
- git reset --hard [commitId](撤销并舍弃版本号之后的提交记录)。
- git revert [commitId](撤销,但是保留了提交记录)。
更多推荐
所有评论(0)