一、问题描述

在一次生产发布中,不能把合并到master的新功能发出去,但是生产又有bug要修复,所以master代码要回滚,将develop合并到master的合并提交回滚到master的上一次提交,如下图所示:

上图1是一个合并提交,是将develop分支合并到master分支,有很多特性分支的代码合并到develop分支,我们只要将1回退到2就可以将不要发布出去的功能回退到上次的稳定版本。在图中,我们可以看到1是2和绿色线的合并,我们只要撤销提交1就可以回到提交2,这时绿色线合并过来的代码就会全部撤销掉了,因为git是通过一个个指针指向的,回到2,1的父提交就只有2了。

二、使用git revert回退

团队合作的项目,不建议使用git reset回退公共远程分支,这是非常暴力的做法,风险挺高的。下面我们使用另个一个命令来回退版本:

git revert HEAD                     //撤销最近一次提交
git revert HEAD~1                   //撤销上上次的提交,注意:数字从0开始
git revert 0ffaacc                  //撤销0ffaacc这次提交

git revert命令意思是撤销某次提交。它会产生一个新的提交,虽然代码回退了,但是版本依然是向前的,所以,当你用revert回退之后,所有人pull之后,他们的代码也自动的回退了。
但是,要注意以下几点:

1. revert是撤销一次提交,所以后面的commit id是这个撤销的提交的commit id
2.使用revert HEAD是撤销最近的一次提交,如果你最近一次提交是用revert命令产生的,那么你再执行一次,就相当于撤销了上次的撤销操作,换句话说,你连续执行两次revert HEAD命令,就跟没执行是一样的
3. 使用revert HEAD~1 表示撤销最近2次提交,这个数字是从0开始的,如果你之前撤销过产生了commit id,那么也会计算在内的。
4. 如果使用 revert 撤销的不是最近一次提交,那么一定会有代码冲突,需要你合并代码,合并代码只需要把当前的代码全部去掉,保留之前版本的代码就可以了.

git revert 命令的好处就是不会丢掉别人的提交,即使你撤销后覆盖了别人的提交,他更新代码后,可以在本地用 reset 向前回滚,找到自己的代码,然后拉一下分支,再回来合并上去就可以找回被你覆盖的提交了。

三、解决方案

  1. 使用git log找到1的commit id:5653712d
  2. 使用git revert head命令或者git revert 5653712d本地回滚
  3. 但是报错了:

    由于commit5653712d是一个合并提交,和普通 commit 的不同之处在于 merge commit 包含两个 parent commit,代表该 merge commit 是从哪两个 commit 合并过来的。直接使用 git revert ,git 也不知道到底要撤除哪一条分支上的内容,这时需要指定一个 parent number 标识出"主线",主线的内容将会保留,而另一条分支的内容将被 revert。
  4. revert merge commit有一些不同,这时需要添加-m选项以代表这次revert 的是一个 merge commit。
    使用git show命令可以查看 commit 的详细信息如下图:

这代表该 merge commit 是从 e22a0e3 和 f2c74c6 两个 commit 合并过来的。
而常规的 commit 则没有 Merge 行:

  1. 如上面的例子中,从 git show 命令的结果中可以看到,merge commit 的 parent 分别为 e22a0e3 和 f2c74c6,其中 e22a0e3 代表 master 分支,f2c74c6 代表 develop 分支。我们可以在master分支上使用git log查看提交日志:

从上图可以看到e22a0e3代表master分支上的父提交。需要注意的是 -m 选项接收的参数是一个数字,数字取值为 1 和 2,也就是 Merge 行里面列出来的第一个还是第二个。
7. 我们要revert develop分支上的内容,即保留主分支master,应该设置主分支为主线,操作如下:

git revert -m 1 5653712d
  1. 有冲突的话,处理冲突,然后commit和push

四、idea解决方案

在需要revert的commit上执行revert commit,然后再commit和push,和在git bash命令行工具上使用命令git revert是一样的,本来idea也是使用这个命令,如图:

比如,要回滚提交 uml类图时序图,那只要在这个提交上右键选择revert commit,然后commit和push就可以。但是要注意,如果我们要回滚多次提交,则要按照提交相反的顺序进行revert,也就是说最后提交的代码最先revert,否则可能会产生冲突。


上图中,代码提交顺序是3->2->1,如果我们想1、2、3都revert掉,那么可以按照1->2->3的顺序进行revert然后提交即可。如果你想恢复被revert的代码,那么你可以按照同样的方式revert你的revert提交即可。

需要说明的是,idea上只能revert普通commit,merge commit上的revert commit置灰不能使用。

五、参考资料

  1. Git之revert
  2. [译]Git回滚合并
  3. [Git高级教程(二)] 远程仓库版本回退方法
  4. Git学习笔记git revert
  5. git操作技巧之Revert(Intellij Idea环境下)
  6. IDEA远程仓库版本回滚
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐