“回滚”和“rollback”——指将系统、代码或数据恢复到先前状态的术语。在开发中,这是一个基本操作,内置于版本控制系统、数据库和部署机制中。根据 Git Documentation,回滚操作可以是安全的(通过创建新提交的 revert)和破坏性的(通过丢失历史的 reset)。理解它们之间的区别有助于在恢复到先前版本时避免数据丢失。
要点
回滚(rollback)——将系统恢复到先前稳定状态的操作。在开发环境中,这可能意味着撤销Git中的提交、回滚数据库中的事务或在服务器上恢复应用程序的先前版本。该术语源自英语“rollback”,并已牢固地扎根于所有平台开发者的词汇表中。
当新更改破坏功能、引发错误或未通过质量检查时,就需要进行回滚。在组织良好的开发流程中,回滚不是失败的标志,而是工作流程中的标准程序。团队能越快回滚有问题的更改,错误对用户的影响就越小。
不同的工具提供不同的回滚机制:Git提供安全revert和破坏性reset之间的选择,数据库支持事务性rollback,而CI/CD系统可以在版本之间切换流量。方法的选择取决于上下文和对变更历史保存的要求。
Git revert——安全的回滚方式,通过创建新提交来撤销先前提交的更改。历史保持线性,所有旧提交都得以保留。对于多人协作的共享分支,这是唯一正确的选择。git revert命令不会删除历史——它将回滚的事实作为新更改添加进来。
Git reset将当前分支指针移动到指定提交,丢弃所有后续更改。根据标志(soft、mixed或hard),reset对工作目录和索引的处理方式不同。hard模式将更改从历史中完全删除,使其对共享分支有危险,仅适用于本地工作。
Revert用于共享分支:main、develop、release。它保留历史,让其他开发者了解更改已被撤销。revert后可以安全地执行git pull——系统不会出现与重写历史相关的冲突。在团队协作中,revert是默认标准。
# 通过创建新提交来撤销最后提交
git revert HEAD
# 通过哈希撤销特定提交
git revert a1b2c3d
Reset适用于尚未发布更改的本地分支。如果您在进行实验并希望完全清理历史——reset hard可以做到这一点。在本地分支中,可以使用reset mixed来撤销提交,但保留工作目录中的更改以便重新提交。
# 撤销最后提交,保留工作目录中的更改
git reset HEAD~1
# 完全撤销——更改将被永久删除
git reset --hard HEAD~2
事务回滚——撤销当前事务中所做所有更改的操作,将数据库恢复到事务开始时的状态。这保证了原子性——ACID(Atomicity原子性、Consistency一致性、Isolation隔离性、Durability持久性)四项原则之一。如果在事务的任何阶段发生错误,则执行rollback并将数据恢复到原始状态。
回滚机制通过预写日志(Write-Ahead Log,WAL)实现。在更改数据页之前,DBMS将旧值和新值记录到日志中。回滚时,系统读取日志并恢复所有已修改数据页的原始值。这保证了即使在断电情况下,事务也能被正确撤销。
BEGIN TRANSACTION;
UPDATE accounts
SET balance = balance - 100
WHERE id = 1;
-- Rollback on error
ROLLBACK;
在长事务中,使用savepoint很方便——中间保存点,可以回滚到该点而无需完成整个事务。这允许在复杂操作内部处理错误,而不会丢失其他部分的进度。大多数关系型DBMS都支持Savepoint:PostgreSQL、MySQL、Oracle。
SAVEPOINT sp1;
UPDATE orders SET status = 'cancelled'
WHERE id = 42;
ROLLBACK TO sp1;
部署回滚——在失败部署后将运行中的应用程序恢复到先前版本。这是生产环境的关键能力:恢复时间(MTTR)直接影响SLA和用户体验。现代平台根据架构和可用性要求提供多种回滚策略。
蓝绿部署——同时运行两个相同的环境:blue(当前版本)和green(新版本)。成功部署后流量切换到green。如果新版本运行不正常,流量开关返回到blue。回滚是即时的,无需重新部署——只需更改路由即可。
金丝雀部署将一小部分流量引导到新版本并监控指标:错误数量、响应时间、成功请求百分比。如果指标恶化,系统自动回滚金丝雀并将所有流量指向稳定版本。Kubernetes和服务网格(Istio、Linkerd)开箱即用地支持这种策略。
apiVersion: apps/v1
kind: Deployment
spec:
replicas: 10
strategy:
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
让我们考虑三种典型场景,开发者需要回滚更改。每个场景都需要不同的方法——从终端中的简单命令到涉及CI/CD的多步骤流程。
您不小心将带有错误的提交推送到了main。您的目标是在不为团队丢失历史的情况下回滚更改。使用git revert创建撤销提交,然后git push。所有团队成员都会看到回滚,并能继续工作而不会产生冲突。这是最安全和最透明的方式。
git checkout main
git pull origin main
git revert HEAD
git push origin main
数据库迁移出错,部分数据已损坏。在迁移脚本中使用事务性rollback,并对已应用的更改从备份恢复。在良好设计的系统中,每次迁移都包裹在事务中——出错时DBMS自动执行rollback。
部署新版本后发现身份验证无法正常工作。如果使用蓝绿部署,回滚就是将路由器切回。如果是滚动更新——kubectl rollout undo命令将恢复先前版本。理想情况下,回滚流程应该是自动化的,最多不超过一分钟。
常见问题
Revert创建新提交撤销更改并保留历史。Reset将分支指针向后移动并可能删除提交。对于共享分支,只使用revert。
如果提交尚未被Git的垃圾回收器收集,可以通过git reflog恢复。然而,垃圾回收后恢复就变得不可能了。--hard只应在本地分支中使用。
Rollback使用预写日志(WAL)撤销当前事务中所有更改。DBMS恢复所有已修改数据页的原始值。
Savepoint——事务内部的中间保存点。允许部分回滚到该点而无需撤销整个事务。适用于包含多个步骤的长操作。
部署后设置健康检查和指标监控。当错误阈值超过时,通过脚本或工具如Spinnaker、ArgoCD或GitLab Auto Rollback触发自动回滚。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。