刚入行时被reset和revert搞晕过好几次,后来理清了本质区别:reset是移动HEAD指针,revert是创建反向提交。场景不同,用法完全不同。
reset:本地分支回退,适合还没push的提交
reset有三种模式,区别在于工作区和暂存区怎么处理。
# 最常用,只移动HEAD,工作区代码不动
git reset --soft HEAD~1
# 默认模式,移动HEAD并清空暂存区,工作区代码保留
git reset --mixed HEAD~1
# 最暴力,移动HEAD并清空暂存区,工作区代码也被覆盖
git reset --hard HEAD~1
举个例子:刚提交了一个bug,但还没push,想撤销这次提交但保留改动的代码继续改。
git reset --soft HEAD~1
# 文件改动保留在暂存区,可以直接重新commit
如果连暂存区都不想保留,只想让文件回到改之前:
git reset --mixed HEAD~1
# 或者直接 git reset HEAD~1,mixed是默认
–hard要慎用,本地没提交的改动会直接丢掉。我吃过一次亏,写了两小时的代码忘了提交,一个reset –hard全没了。
reset还有个参数–keep,介于mixed和hard之间:只回退已提交的,工作区未提交的改动会保留但可能冲突。
revert:远程分支回退,适合已经push的提交
revert不会删除历史,而是创建一个新提交来抵消旧提交的改动。多人协作时必须用这个,否则别人pull下来会乱。
# 撤销最近一次提交
git revert HEAD
# 撤销某次具体提交
git revert abc1234
# 撤销多个提交(会按顺序创建多个反向提交)
git revert HEAD~3..HEAD
revert和cherry-pick本质相同,都是应用一个commit的diff,只不过revert应用的是反向diff。
举例:线上有个bug,是三天前那次提交引入的,已经push到远程了。
# 找到那次提交的hash
git log --oneline
# 假设是 a1b2c3d
git revert a1b2c3d
# 会弹出编辑器让你写commit message,默认是"Revert 'xxx'"
# 保存后就会生成一个新提交,内容正好抵消掉a1b2c3d的改动
revert可能会冲突,如果那次提交之后有其他改动改到了同一行。解决冲突跟普通merge一样,解决完git revert –continue。
什么时候用reset,什么时候用revert
– 本地分支、还没push:用reset,干净利落
– 已经push到远程、但只有你自己在用这个分支:可以用resetforce push,但要通知团队
– 已经push到远程、多人协作:必须用revert,别坑队友
– 想撤销中间某次提交、但后面的改动还要保留:用revert指定那次提交
– 想彻底删除某段历史(比如误提交了密码):用reset + force push,但要注意其他同事已经拉取过
git revert –no-commit可以手动合并多个revert
# 不自动提交,把所有反向改动放到工作区
git revert --no-commit HEAD~3..HEAD
# 手动检查改动,一次性提交
git commit -m "Revert last 3 commits"
这个技巧适合需要处理复杂冲突的场景,可以逐行审查反向改动。
还有个东西叫git restore,是git 2.23引入的,用来替代git checkout的部分功能。它专门处理工作区和暂存区的文件恢复,跟reset和revert定位不同。
# 把某个文件恢复到上次提交的状态
git restore file.txt
# 从暂存区恢复到工作区
git restore --staged file.txt
简单总结:reset是时光机,revert是补丁。想抹掉历史用reset,想保留历史但撤销改动用revert。记住一条铁律:已经push到公共分支的提交,永远用revert。
另外,如果团队用雨云做CI/CD,代码回退后记得重新部署。雨云的部署流程支持指定commit回滚,直接在控制台点一下就能切到历史版本,省得本地重新push。不过这是题外话,回退操作本身跟部署平台无关。
雨云是国内一家老牌云服务商,提供高性价比的云服务器和虚拟主机。我用它部署了好几个项目,速度和稳定性都不错。通过 https://www.rainyun.com/SAJA_ 注册可以领一张 5折优惠券,有需要的朋友可以看看。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END



暂无评论内容