我的项目包含两个重要git分支:master(生产环境),develop(测试环境)。
正常的开发流程为:从master剪分支,然后进行开发,开发后合并到develop分支,当测试通过后合并到master分支进行上线。
所以,master分支和develop分支代码差别很大,包括:未上线的代码,针对develop做的特殊处理等等。
但某人错误操作,不小心从develop剪分支,最终合并到了master分支,造成develop的分支跑到了master分支上,造成生产问题。
所以需要对合并进行回退。
首先,我们master上有两个提交记录:
develop上也对应也有两个提交记录
此时我们新建一个version-20221107的分支,本应该从master上剪,结果错误的从develop上剪了。
此时,我们将version-20221107合并到master上(假设没有冲突):
之后会发现,develop的代码出现在了master上。
我们来查看master的提交记录:
会发现除了包含合并记录外,也包含develop的提交记录,这也是回退过程中最令人头疼的情况。
git reset --hard
命令说明:git reset --hard
命令是强制回到某一个版本,然后利用git push -f
命令强制推到远程
优点:干净利落,回滚后完全回到最初状态。
缺点:
不管优点缺点吧,来试一下:
我们是要回退到master commit2
, 但是在实际中,我们并不能一眼就看出哪些是develop的提交记录,所以很难定位到要回退到哪个版本,所以要配合如下命令:
查看分支的提交情况
git reflog
输出:
70ca41f (HEAD -> master-test, origin/master-test) HEAD@{0}: commit (merge): Merge remote-tracking branch 'origin/version-20221107' into master-test
9e47366 HEAD@{1}: checkout: moving from master to master-test
可以看到,通过该命令,并不会出现像gitlab上那么多提交记录,所以9e47366
就是我们要回滚的分支。
接下来,就是强制回滚:
git reset --hard 9e47366
然后强制push
git push -f
然后再来看下git提交记录,发现合并的都没了
上述查找版本到reset的都可以用
git reset --hard HEAD~1
代替,HEAD~1
表示回退到上一版本。不过个人推荐还是一步一步做,不容易出错
假设上述动作是第二天才做的,中间有一个人又从master上拉了一个version-202221108
的分支:
我们做回退的也不知道,这个时候假设他把version-20221108
合并到master上,看看会发生什么情况:
最后发现白回滚了,回滚的代码又回来了。这也缺点中的第三条。
不过用revert
命令回滚可以避免该问题。
git revert
命令说明:revert
命令是“回滚”,即回滚某一次的操作。我们可以利用该来撤销合并错误。其原理为:撤销上一个版本的操作,会生成一个新的版本。相当于一次重新提交,只不过这次的提交的内容就是把上次提交的内容给还原。
优点:
缺点:不够干净,还会保留错误合并的提交记录。
接下来我们来实验下:
目前,我们需要对合并操作进行回滚,也就是对70ca41f4
这个提交。我们只需要使用如下命令:
git revert 70ca41f4 -m 1
-m 1
是固定的,可以理解保留当前分支的代码,回滚掉来源分支的代码。
在执行完该命令后,会弹出输入comment信息,确定后,进行push即可。
之后可以看到生成了一条revert的记录,并且代码也回退到原状。
此时,我们再将version-20221108
合并到master,结果如下(已处理冲突):
可以看到,虽然version-20221108
分支是在回滚前剪出的,但并不会把develop的代码合并进来。
假设有人在回滚前又提交了代码:
使用Revert命令并不会对其造成影响。
说明:直接使用gitlab页面进行操作,原理与使用revert命令一致。
优点:
缺点:如果你回滚的版本后面有提交,那么页面无法自动完成,需要用命令。
首先,我们选择要回滚的合并提交记录(注意:这里要选择的是“你要回滚的提交,而不是你要回滚到哪个版本”):
选择Revert
选择要Revert的分支
最后点击Revert就行了。