includeios / document

js玄学
27 stars 2 forks source link

如何优雅的进行版本回退 #12

Open includeios opened 5 years ago

includeios commented 5 years ago

如何优雅的进行版本回退

平时合代码时,难免会将一些不需要的代码合到主分支里。

像我就经常遇到合完qa_test后,又和我说这个功能今天上不了了,希望我能把这部分功能从qa_test里踢出去。以前我的做法都是找到那条合代码的commit记录,checkout到之前版本,在新起个分支作为这次上线的qa_test,就怕莫名其妙的删除和回滚导致后面代码合不上去….

后来弄懂了git reset 和 git revert,才知道自己的做法是多么的傻逼。

回滚的常用两个命令

git reset
git revert

这两个命令具体有什么区别呢?怎么用他们做回滚呢?

git reset

假设我们系统里有下面这些提交记录: image

A版本和B版本是我们正常的提交,C版本和D版本是错误提交,现在我们希望回退到B版本。

此时,HEAD指针指向D(5lk4er),我们只要将HEAD指针指向B(a0fvf8),就OK了,于是:

git reset --hard a0fvf8

运行完命令后,本地HEAD指针如期望指向了B,如下图: image

然而此时,远程仓库的HEAD指针依旧指向D,这个时候是提交不上去的。所以我们只能强制提交,覆盖掉远程分支的记录:

git push -f

采用这种方法回滚的弊端显而易见:他会强制HEAD指针往回移动,丢弃后面版本的代码,如果后来发现C和D是多么绝妙的想法,他们也丢失在历史的长河了。

git revert

revert不一样的是他会反向新创建一个版本,这个版本的内容与我们需要回滚的版本内容一样,HEAD会指向这个新的版本,而不是回退到之前版本。

还是上面那个例子,想要回滚到版本B,我们先需要回滚一下D,再回滚一下C(根据提交的顺序反向回滚):

git revert 5lk4er
git revert 76sdeb

这个时候我们会新生成两个对应的分支D'和C',HEAD指向我们最后生成的C'版本,其中的代码和B版本一模一样。如下图: image

这里是需要回退两个版本,那如果有好多个版本有没有什么简便的快捷写法呢:

//git revert 最后一个要回滚的版本号^..第一个要回滚的版本号
git revert OLDER_COMMIT^..NEWER_COMMIT

这种回滚,错误C和D依旧有迹可循,也可以在历史的长河里再次拾起这两枚遗珠。而且,这里HEAD是往后移的,push到远程分支直接push就好。

玩个高级点的

上面那个例子还是比较简单的,现实场景中我们经常遇到下面这种情况:错误提交的版本刚好在中间,希望既保留A又保留C,只把B踢了: image

直接revert到A肯定是不够的,我们还需要保留C的代码,常见做法是先回退C,回退B,再通过cherry-pic命令添加C版本的代码:

git revert 76sdeb^..a0fvf8
git cherry pic 76sdeb

image

最后,感谢这篇文章让我重获新生:https://www.itcodemonkey.com/article/13010.html

dogelin commented 3 years ago

感谢,写得很详细

Seayon commented 3 years ago

谢谢,太棒了!

zhang156 commented 3 years ago

git revert 76sdeb^..a0fvf8

这里是不是反了

LIUXUCHONG commented 2 years ago

git revert 76sdeb^..a0fvf8

这里是不是反了

确实写反了 应该把最老的commit放前面