git 如何撤销历史某次merge

git,如何 撤销某一次历史提交或merge,并保留该版本的后续提交?

场景1:

你有两个功能迭代版本的分支,一个是 15 号上线,一个是25号上线。5号的时候产品突然说,这两个版本一起上,然后你耿直的把25号版本merge到了15号版本。

几天后产品说:“一起上有问题,我们还是分开上吧”。这个时候你发现merge之后又提交了很多15号版本的代码,需要撤销那次merge并且保留后面的提交。

场景2:

所有人共用 test 分支,有五个人都在这上面合并了自己的代码,结果有天 A 不小心把 develop 分支合并到了 test,过了一会 A 发现,并且想撤回的时候,发现再次期间,有好几个人都提交了代码。所以不能用reset,而是需要撤销merge并且保留后面更改。

git revert

git revert -m 1 commitId

Git 之 revert

revert 可以取消指定的某次提交内容。

当讨论 revert 时,需要分两种情况,因为 commit 分为两种:一种是常规的 commit,也就是使用 git commit 提交的 commit;另一种是 merge commit,在使用 git merge 合并两个分支之后,你将会得到一个新的 merge commit。

merge commit 和普通 commit 的不同之处在于 merge commit 包含两个 parent commit,代表该 merge commit 是从哪两个 commit 合并过来的。

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

➜  git show bd86846
commit bd868465569400a6b9408050643e5949e8f2b8f5
Merge: ba25a9d 1c7036f

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

而常规的 commit 则没有 Merge 行

➜  git show 3e853bd
commit 3e853bdcb2d8ce45be87d4f902c0ff6ad00f240a

revert 常规 commit

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

revert merge commit

revert merge commit 有一些不同,这时需要添加 -m 选项以代表这次 revert 的是一个 merge commit

但如果直接使用 git revert ,git 也不知道到底要撤除哪一条分支上的内容,这时需要指定一个 parent number 标识出"主线",主线的内容将会保留,而另一条分支的内容将被 revert。

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

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

➜ git revert -m 1 bd86846

revert 之后重新上线

假设狗蛋在自己分支 goudan/a-cool-feature 上开发了一个功能,并合并到了 master 上,之后 master 上又提交了一个修改 h,这时提交历史如下:

a -> b -> c -> f -- g -> h (master)
           \      /
            d -> e   (goudan/a-cool-feature)

突然,大家发现狗蛋的分支存在严重的 bug,需要 revert 掉,于是大家把 g 这个 merge commit revert 掉了,记为 G,如下:

a -> b -> c -> f -- g -> h -> G (master)
           \      /
            d -> e   (goudan/a-cool-feature)

然后狗蛋回到自己的分支进行 bugfix,修好之后想重新合并到 master,直觉上只需要再 merge 到 master 即可(或者使用 cherry-pick),像这样:

a -> b -> c -> f -- g -> h -> G -> i (master)
           \      /               /
            d -> e -> j -> k ----    (goudan/a-cool-feature)

i 是新的 merge commit。但需要注意的是,这 不能 得到我们期望的结果。因为 d 和 e 两个提交曾经被丢弃过,如此合并到 master 的代码,并不会重新包含 d 和 e 两个提交的内容,相当于只有 goudan/a-cool-feature 上的新 commit 被合并了进来,而 goudan/a-cool-feature 分支之前的内容,依然是被 revert 掉了。

所以,如果想恢复整个 goudan/a-cool-feature 所做的修改,应该先把 G revert 掉:

a -> b -> c -> f -- g -> h -> G -> G' -> i (master)
           \      /                     /
            d -> e -> j -> k ----------    (goudan/a-cool-feature)

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

参考:

http://blog.psjay.com/posts/git-revert-merge-commit/
https://stackoverflow.com/questions/9059335/how-to-get-the-parents-of-a-merge-commit-in-git

于2024年4月-2025年9月期间,研究团队在贵州习水国家级自然保护区制定39条样线,涵盖灌木林、常绿阔叶林、针叶林、常绿落叶阔叶混交林、针阔混交林等不同植被类型,每条样线分春夏秋冬4个季节采集样品,用真菌采集软件记录经纬度、海拔、采集地点、时间、生境等信息,使用佳能相机(R6 mark Ⅱ)对大型真菌进行拍照,并采集标本,标本存放于贵州省生物研究所大型真菌标本馆(HGAMF)。 通过形态学初步鉴定,结合分子生物学最终鉴定,参考已]报道的中国毒蘑菇名录开展毒蘑菇的认定。 调查到保护区内有毒真菌7目25科64种,导致中毒的主要类型有急性肾衰竭型、神经精神型和胃肠炎型。最终形成贵州习水国家级自然保护区大型有毒真菌图片数据集,它由以下2个部分组成。 (1)附件1包含78张原始照片(.JPG),照片名字包括了大型有毒真菌的拉丁名和中文名,若无中文名的直接用拉丁名。 (2)附件2是一个压缩文件,包含了2张工作表,其中一张表是大型有毒真菌39条样线的信息,另一张表是大型有毒真菌的中毒类型。 照片采用佳能相机R6 mark Ⅱ拍摄,物种鉴定通过多种文献核实,并经两位以上专家鉴定确认。该数据集可为研究地及周边的普通人识别有毒大型真菌提供参考,通过及时的图片对比,能有效避免误采误食大型有毒真菌,同时为因误食大型真菌可能引发的身体损伤进行了总结,能为患者及时治疗提供参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值