git 线上回滚问题纪要

1. git revert 做用

  revert 用来取消置顶的提交的内容git

2. 前提说明

  当讨论 revert 时,须要分两种状况,由于 commit 分为两种:spa

  • 一种是常规的 commit,也就是使用 git commit 提交的 commit;
  • 另外一种是 merge commit

  须要明确:在使用 git merge 合并两个分支以后,你将会获得一个新的 merge commit。merge commit 和普通 commit 的不一样之处在于 merge commit 包含两个 parent commit,表明该 merge commit 是从哪两个 commit 合并过来的。code

  

  在上图所示的红框中有一个 merge commit,使用 git show 命令能够查看 commit 的详细信息blog

  ➜  git show bd86846
  commit bd868465569400a6b9408050643e5949e8f2b8f5
  Merge: ba25a9d 1c7036f

   这表明该 merge commit 是从 ba25a9d 和 1c7036f 两个 commit 合并过来的。开发

  而常规的 commit 则没有 Merge 行it

  ➜  git show 3e853bd
  commit 3e853bdcb2d8ce45be87d4f902c0ff6ad00f240a

 3. revert 常规 commit

  使用 git revert <commit id> 便可,git 会生成一个新的 commit,将指定的 commit 内容从当前分支上撤除。ast

4. revert merge commit

  revert merge commit 有一些不一样,这时须要添加 -m 选项以表明此次 revert 的是一个 merge commitclass

  但若是直接使用 git revert <commit id>,git 也不知道到底要撤除哪一条分支上的内容,这时须要指定一个 parent number 标识出"主线",主线的内容将会保留,而另外一条分支的内容将被 revert。bug

  如上面的例子中,从 git show 命令的结果中能够看到,merge commit 的 parent 分别为 ba25a9d1c7036f,其中 ba25a9d 表明 master 分支(从图中能够看出),1c7036f 表明 will-be-revert 分支。须要注意的是 -m 选项接收的参数是一个数字,数字取值为 1 和 2,也就是 Merge 行里面列出来的第一个仍是第二个。im

  咱们要 revert will-be-revert 分支上的内容,即 保留主分支,应该设置主分支为主线,操做以下:

  ➜ git revert -m 1 bd86846

5. revert 以后从新上线

  假设你本身分支 goudan/a-cool-feature 上开发了一个功能,并合并到了 master 上,以后 master 上又提交了一个修改 h,这时提交历史以下:

  

   忽然,你们发现你的分支存在严重的 bug,须要 revert 掉,因而你们把 g 这个 merge commit revert 掉了,记为 G,以下:

  

   而后你回到本身的分支进行 bug_fix,修好以后想从新合并到 master,直觉上只须要再 merge 到 master 便可

  

   i 是新的 merge commit。但须要注意的是,这 不能 获得咱们指望的结果。由于 d 和 e 两个提交曾经被丢弃过,如此合并到 master 的代码,并不会从新包含 d 和 e 两个提交的内容,至关于只有 goudan/a-cool-feature 上的新 commit 被合并了进来,而 goudan/a-cool-feature 分支以前的内容,依然是被 revert 掉了。

  因此,若是想恢复整个 goudan/a-cool-feature 所作的修改,应该先把 G revert 掉:

  

   其中 G' 是对 G 的 revert 操做生成的 commit,把以前撤销合并时丢弃的代码恢复了回来,而后再 merge 狗蛋的分支,把解决 bug 写的新代码合并到 master 分支。

  能够通俗的来理解:相对你本身 G 是经过别人来远程操做的 revert 操做,相对于别人来讲此时的 master 分支已经不存在 d 和 e 两个提交的内容,而你本身本地分支上并无进行 revert 操做,相对于其余人来讲你本地认为 master 分支还保存有 d 和 e 提交的内容,若是直接合并的话会报错,故须要你本身在本地直接 revert 操做,将 g 点联系释放掉,和线上原始 master 分支保持干净完整的链路,这样就能够正常的 merge commit 了。

6. revert 和 reset 区别

  1. git revert 是用一次新的 commit 来回滚以前的 commit,git reset 是直接删除指定的 commit。 
  2. 在回滚这一操做上看,效果差很少。可是在往后继续 merge 之前的老版本时有区别。由于 git revert 是用一次逆向的 commit “中和” 以前的提交,所以往后合并老的 branch 时,致使这部分改变不会再次出现,可是 git reset 是直接把某些 commit 在某个 branch 上删除,于是和老的 branch 再次 merge 时,这些被回滚的commit应该还会被引入。 
  3. git reset 是把 HEAD 向后移动了一下,而 git revert 是HEAD继续前进,只是新的 commit 的内容和要 revert 的内容正好相反,可以抵消要被 revert 的内容。
相关文章
相关标签/搜索