相对于常规的 commit,当使用 git merge 合并两个分支的时候,你会得到一个新的 merge commit。
当我们 git show 的时候会出现类似信息:
1commit 6dd0e2b9398ca8cd12bfd1faa1531d86dc41021a
2Merge: d24d3b4 11a7112
3Author: test
4...............
Merge: d24d3b4 11a7112 这行表明了两个分支在合并时,所处的 parent 的版本线索。
比如在上述项目中我们开出了一个 dev 分支并做了一些操作,现在分支的样子变成了这样:
1init -> v1 -> v2 -> v3 (master)
2 \
3 d1 -> d2 (dev)
当我们在 dev 开发的差不多了:
1#git:(dev)
2git checkout master
3#git:(master)
4git merge dev
这个时候形成了一个 Merge Commit faulty merge:
1init -> v1 -> v2 -> v3 -- faulty merge (master)
2 \ /
3 d1 --> d2 (dev)
此时 faulty merge 有两个 parent 分别是 v3 和 d2。
回滚错误的合并这个 merge 之后还继续在 dev 开发,另一波人也在从别的分支往 master 合并代码。变成这样:
1init -> v1 -> v2 -> v3 -- faulty merge -> v4 -> vc3 (master)
2 \ \ / /
3 \ d1 --> d2 --> d3 --> d4 (dev)/
4 \ /
5 c1 --> c2 -------------------c3 (other)
这个时候你发现, 妹的,上次那个 merge 好像给共享分支 master 引入了一个 bug。这个 bug 导致团队其他同学跑不通测试,或者这是一个线上的 bug,如果不及时修复老板要骂街了。
这个时候第一想到的肯定是回滚代码,但怎么回滚呢。用 reset?不现实,因为太流氓不说,还会把别人的代码也干掉,所以只能用 revert。而 revert 它最初被设计出来就是干这个活的。
怎么操作呢?首先想到的是上面所说的 git revert ,但是貌似不太行。
1git revert faulty merge
2error: Commit faulty merge is a merge but no -m option was given.
3fatal: revert failed
这是因为试图撤销两个分支的合并的时候 Git 不知道要保留哪一个分支上的修改。所以我们需要告诉 git 我们保留那个分支 m 或者 mainline。
1git revert -m 1 faulty merge
-m 后面带的参数值可以是 1 或者 2,对应着 parent 的顺序。
上面列子:1 代表 v3,2 代表 d2。
所以该操作会保留 master 分支的修改,而撤销 dev 分支合并过来的修改。提交历史变为:
1init -> v1 -> v2 -> v3 -- faulty merge -> v4 -> vc3 -> rev3 (master)
2 \ /
3 d1 --> d2 --> d3 --> d4 (dev)
此处 rev3 是一个常规 commit,其内容包含了之前在 faulty merge 撤销掉的 dev 合并过来的 commit 的(反操作)的合集。
到这个时候还没完,我们要记住,因为我们抛弃过之前 dev 合并过来的 commit,下次 dev 再往 master 合并,之前抛弃过的其实是不包含在里面的。那怎么办呢?
恢复之前的回滚很简单,我们把之前 master 那个带有反操作的 commit 给撤销掉不就好了?
1git checkout master
2git revert rev3
3git merge dev
此时提交历史变成了:
1init -> v1 -> v2 -> v3 -- faulty merge -> v4 -> vc3 -> rev3 -> rev3` -> final merge (master)
2 \ / /
3 d1 --> d2 --> d3 --> d4 --------------------------------(dev)
你学会这个骚操作了吗?评论区见!
▼往期精彩回顾▼卧槽!Java 长整数的这个坑你踩过吗?唉,因为 Java 的装逼简化炫技写法背锅了!
点击左下角阅读原文查看历史经典技术问题汇总,看完顺手走一波PYQ呀~