背景
之前的文章讲解了单个开发分支场景下的回退 juejin.cn/post/686706…
但是实际的多人开发中 可能每个人都有自己的一个开发分支 当大家都往master去合并的时候 ,这时就会产生一个merge的记录 而这个merge记录的回退跟我们前面介绍的单开发分支的回退还有一些区别 ,他不再是一个线性的历史 而是一个树形的多分支历史,这里会引入 git revert的一个重要参数 -m (--mainline的简写)
场景还原
我们先模拟出来这个场景 一个主分支master 两个开发分支 dev-01 和 dev-02
# 初始化项目 并切出两个开发分支 模拟两个人并行开发
git init
echo 'init' >> readme.txt
git add .
git commit -m 'init'
git checkout -b dev-01
git checkout -b dev-02
# 分支dev-02 新增一个文件 改动一个文件
echo '开发2的修改' >> readme.txt
echo '2222' > 2.txt
git add .
git commit -m '开发2的修改'
# 分支dev-01 同样新增一个文件 改动一个文件
git checkout -b dev-01
echo '开发1的修改' >> readme.txt
echo '1111' > 1.txt
git add .
git commit -m '开发1的修改'
# 回到master分支 先 合并dev-01 再合并 dev-02
git checkout master
git merge dev-01
# 在我们合dev-02的时候,因为都修改了 readme.txt这个文件的,一定会有冲突
git merge dev-02
再合并dev-02的时候一定会有冲突,我们 手动修改readme.txt 解决冲突, 然后提交
# 模拟解决冲突
vim readme.txt
git add .
git commit -m '合并冲突'
git log --graph --oneline
最后readme.txt的内容为
init
开发1的修改
开发2的修改
文件有三个
1.txt 2.txt readme.txt
日志的输出为
* ad1abf8 (HEAD -> master) 合并冲突
|\
| * a237d48 (dev-02) 开发2的修改
* | 9137aff (dev-01) 开发1的修改
|/
* e247e5a init
处理问题
场景介绍的有点长,但其实并不复杂,主要还原了 两个人并行开发,然后合并到master的场景,此时如果我们想回退某个人的操作改怎么办呢? 比如我们要撤销开发1的修改 按上篇文章的知识 我们直接 git revert 9137aff可以么? 答案是可以的 但是会产生冲突 需要我们手动的去处理冲突,因为我能跨过了最新的ad1abf8去进行revert,git不知道该用最新的代码还是用你revert的那个旧的代码了,就把问题丢给了操作者,让操作者去解决冲突,那有啥办法不冲突的顺滑回退么 ? 答案是revert那次分支合并
我们试一下 git revert ad1abf8
git 会报一个这样的错
error: commit ad1abf80a066e238946d998817a008f5f59ae0be is a merge but no -m option was given. fatal: revert failed
好的,铺垫了半天,终于到了今天要重点讲解的地方了
报错告诉我们revert的是一个merge类型的提交,从图里就能看出,他是两个分支的交汇处,那既然要回退 ,git就要知道 我们是要会退到哪条路线上 ,最早提交的dev-01那个是路线1 后来提交的 dev-02那个是路线2 ,对应的参数就是我们前面说的 -m 后面跟一个数字来代表要恢复到哪条路线,好 我们来 实际操作一下
假如现在我们要回退dev-01的修改 ,我们要回到哪条路线呢?当然是 2号线
# 回退到路线2
git revert -m 2 ad1abf8
cat readme.txt
git log --oneline --graph
此时 我们查看文件 1.txt 消失了 只有 2.txt 且 readme.txt的修改也只保留了 dev-02的修改
# 日志现在的样子
* 01681a7 Revert "合并冲突"
* ad1abf8 合并冲突
|\
| * a237d48 (dev-02) 开发2的修改
* | 9137aff (dev-01) 开发1的修改
|/
* e247e5a init
如果我们要回退dev-02的修改呢?先用我们的套娃大法revert掉我们刚才的revert,有点饶舌o( ̄︶ ̄)o
# 通过再次的revert还原现场
git revert 01681a7
# 回退到线路1
git revert -m 1 ad1abf8
查看效果的话 2.txt 消失了 readme.txt的修改也只保留了 dev-01的修改,你可能会问 不是跨 提交进行revert会冲突么,我的理解是 我们跨的是revert类型的提交,而revert类型的提交不会像处理冲突那种有不可预知的修改,逻辑上git自己是知道该如何处理的 所以没有报冲突
好的revert完后续的改bug再次合并等处理流程 就跟上篇文章介绍的一样了 不再赘述