比尔萄堡

上帝说: “要有光” 于是,就有了光。


  • 首页

  • 归档

  • 关于我

  • 公益404

  • 搜索

revert a faulty merge

时间: 2022-02-23 分类: git   字数: 1249 字 阅读: 3分钟 阅读次数:

场景:主线是master分支,从某个分岔点切出topic分支,进行了commit A,commit B,然后将topic merge 到 master。大家继续在 master 上 commit,到某一个时间点,发现commit B有问题,这时候你会怎么做?

 ---o---o---o---M---x---x---    master
               /
       ---A---B                 topic

如果我们对merge进行revert,执行命令$ git revert -m 1 M,生成一个W commit:

 ---o---o---o---M---x---x---W
               /
       ---A---B

topic分支上进行了对 B的修复,形成了commit C, commit D:

 ---o---o---o---M---x---x---W---x             master
               /
       ---A---B-------------------C---D       topic

where C and D are to fix what was broken in A and B, and you may already have some other changes on the mainline after W.

如果此时将topic merge 到 master,会有什么问题吗?

A,B 的 修改会丢失。

为什么会出现这种情况: revert只对 指定的 commit 进行了undo,但是并未对 历史 进行 undo。 即使对merge进行了revert,merge的 commit历史 仍然存在,未来再次merge时,会以上次merge作为基础。

在这种情况下我们要对 revert 进行 revert(Y 是 W 的revert):

 ---o---o---o---M---x---x---W---x---Y
               /
       ---A---B-------------------C---D

效果相当于:

 ---o---o---o---M---x---x-------x----
               /
       ---A---B-------------------C---D

可以将topic merge 到master

 ---o---o---o---M---x---x-------x-------*
               /                       /
       ---A---B-------------------C---D

警惕一种情况,在revert merge后,topic分支被丢弃,新起一个topic’分支,添加了原A, B 的修改。

 ---o---o---o---M---x---x---W---x---x
               /                 \
       ---A---B                   A'--B'--C'

如果在这种revert进行revert:

 ---o---o---o---M---x---x---W---x---x---Y---*
               /                 \         /
       ---A---B                   A'--B'--C'

将topic’ merge 到 master 时,会出现大量代码重叠,冲突。要避免这种情况。

 ---o---o---o---M---x---x---W---x---x---x---*
               /                 \         /
       ---A---B                   A'--B'--C'

这种情况下,直接合并即可,主线上相当于既没有 faulty merge,也没有其revert。

To recap, these are two very different scenarios, and they want two very different resolution strategies:

  • If the faulty side branch was fixed by adding corrections on top, then doing a revert of the previous revert would be the right thing to do.

  • If the faulty side branch whose effects were discarded by an earlier revert of a merge was rebuilt from scratch (i.e. rebasing and fixing, as you seem to have interpreted), then re-merging the result without doing anything else fancy would be the right thing to do. (See the ADDENDUM below for how to rebuild a branch from scratch without changing its original branching-off point.)

However, there are things to keep in mind when reverting a merge (and reverting such a revert).

考虑到revert,并不是单纯的做了undo,而是一次可能包含大量更改的提交。操作时要衡量利弊。一个revert包含大量更改时,不便于日志查看及调试。当然,技术上来说,git revert本身没有问题。

如果条件允许,尽可能还是在原分支,进行修复,再次merge,而不是对merge进行revert。或者只对merge前的某个commit进行revert。

发生revert后,还可以通过重建分支,方便日后正常merge:

 P---o---o---M---x---x---W---x
  \         /
   A---B---C

若通过执行git rebase -i选择 pick A commit,回到A状态,增补正确的代码,形成B’,C’:

 P---o---o---M---x---x---W---x
  \         /
   A---B---C   <-- old branch
    \
     B'---C'   <-- naively rewritten branch

这时会有一个两难的境地,如果合并 A-B’-C’到 主线,会丢失A的更改,如果对W进行revert,B‘跟B会冲突。

这是重建分支不够彻底导致的,如果我们把commit A进行改写,就可以正常合并了:

   A'---B'---C'  <-- completely rewritten branch
  /
 P---o---o---M---x---x---W---x
  \         /
   A---B---C

合并后:

   A'---B'---C'------------------
  /                              \
 P---o---o---M---x---x---W---x---M2
  \         /
   A---B---C

通过$ git rebase [-i] --no-ff P可以改写 commit SHA ID

You can also use –no-ff in cases where you just add extra commits to the topic to fix it up. Let’s revisit the situation discussed at the start of this howto:

 P---o---o---M---x---x---W---x
  \         /
   A---B---C----------------D---E   <-- fixed-up topic branch

At this point, you can use –no-ff to recreate the topic branch:

$ git checkout E
$ git rebase --no-ff P

yielding

   A'---B'---C'------------D'---E'  <-- recreated topic branch
  /
 P---o---o---M---x---x---W---x
  \         /
   A---B---C----------------D---E

You can merge the recreated branch into the mainline without reverting commit W, and mainline’s history will look like this:

   A'---B'---C'------------D'---E'
  /                              \
 P---o---o---M---x---x---W---x---M2
  \         /
   A---B---C
#git# #merge# #revert#

标题:revert a faulty merge

作者:训导主任林作栋

声明: 本博客文章除特别声明外,均采用 CC BY-NC-SA 3.0许可协议,转载请注明出处!

创作实属不易,如有帮助,那就打赏博主些许茶钱吧 ^_^
WeChat Pay

微信打赏

Alipay

支付宝打赏

Edge下载excel后自动打开网页版
RDS数据库迁移流程
训导主任林作栋

训导主任林作栋

戏谑的码农,北野武的拥趸,李安的迷弟,伍佰的Fans

55 日志
23 分类
62 标签
豆瓣
友情链接
  • Obsidian
  • V2EX
  • 关注黑客与极客
  • 廖雪峰
标签云
  • Linux 6
  • K8s 5
  • 数据库 5
  • Golang 4
  • Etcd 3
  • Mysql 3
  • Ai 2
  • Gitlab 2
  • Postgres 2
  • 前端 2
© 2010 - 2024 比尔萄堡
Powered by - Hugo v0.58.2 / Theme by - NexT
/
Storage by Vercel / 刘 ICP 备 18047355 号
0%