V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
kyonn
V2EX  ›  问与答

[git]git 的一个变基问题.

  •  
  •   kyonn · 2023-03-21 18:26:08 +08:00 · 1098 次点击
    这是一个创建于 392 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最开始分支是这样的

    A-B-C(main)
        |
        |-D-E(dev)
    

    然后发现个 bug,需要合入 main 分支(对应图中的 Q), 但是开发人员误合入了 dev 分支(对应途中的 Q'), 由于 dev 也是公共分支, 不能复写历史, 只能 revert(对应图中的 Q''), 然后最终历史变为下图. 其中 Q 和 Q'是相同的修改, Q''是 Q'的 revert.

    A-B-C-Q(main)
        |
        |-D-E-Q'-Q''(dev)
    

    假设这时开发完成了, 我要把 dev 合回 main. 选择把 dev 变基到最新的 main, 但是由于 rebase 的特性, Q'被认为跟 main 上的 Q 是一样的修改, 被 rebase 自动丢弃了. 最终变为下图. 其中 Q'''跟 Q''是等价的,是针对 Q 或者 Q'的 revert, 这样反而导致主线上的修改 Q 被 dev 回退了, 不符合最终目标.

    A-B-C-Q(main)-D'-E'-Q'''
    

    有一种解决方案是变基前先将 dev 压缩为一条 commit, 缺点是丢失了历史. 不知道 V 友们是否有更好的解决方法? 在保留 dev 分支历史的情况下.

    第 1 条附言  ·  2023-03-21 19:05:56 +08:00
    补充下, dev 分支存在时间比较久, 变基到 main 的时刻不一定会记得有这么个坑, 想看下 git 是否有针对这种情况的可选参数可以设置....
    第 2 条附言  ·  2023-03-21 19:13:27 +08:00
    或者 dev 上除了 revert, 是否有更好的处理方式, 以免给后续的变基挖坑
    24 条回复    2023-03-22 01:30:06 +08:00
    Pastsong
        1
    Pastsong  
       2023-03-21 18:31:11 +08:00
    丢弃掉老的 main 分支,直接从 dev fork 出新的 main 分支
    hsfzxjy
        2
    hsfzxjy  
       2023-03-21 18:47:43 +08:00 via Android
    变基前 dev 回退到 E ?
    kyonn
        3
    kyonn  
    OP
       2023-03-21 18:55:38 +08:00
    @hsfzxjy 实际 dev 开发时间比较久, 不一定会记得有这种 revert.
    kyonn
        4
    kyonn  
    OP
       2023-03-21 18:56:00 +08:00
    @Pastsong 那 main 分支上的 Q 修改就丢了, 因为 dev 上没改这个.
    renmu
        5
    renmu  
       2023-03-21 18:59:26 +08:00 via Android
    那就把 revert 的 commit 再 revert 一次
    kyonn
        6
    kyonn  
    OP
       2023-03-21 19:01:16 +08:00
    @renmu 是指变基完成后再 revert 一遍吗? 实际因为 dev 分支开发比较久, 在变基时不一定记得有这个坑在里面...
    kyuuseiryuu
        7
    kyuuseiryuu  
       2023-03-21 19:01:45 +08:00 via iPhone
    回到 E ,force push ,有需要的话用 ref log 看提交记录,cherry pick Q 之后需要的 commit 。
    kyuuseiryuu
        8
    kyuuseiryuu  
       2023-03-21 19:03:30 +08:00 via iPhone
    @kyuuseiryuu 回不去啊,那没救了……历史记录肯定有这两个 commit 记录的,销不掉了
    kyonn
        9
    kyonn  
    OP
       2023-03-21 19:04:26 +08:00
    @kyuuseiryuu 实际 dev 分支存在时间比较久... 不一定记得有这么个坑在.
    rrfeng
        10
    rrfeng  
       2023-03-21 19:14:52 +08:00
    『但是由于 rebase 的特性, Q'被认为跟 main 上的 Q 是一样的修改, 被 rebase 自动丢弃了. 』
    ----
    没理解这个,这个特性叫啥?我怎么没见过?
    godpeo
        11
    godpeo  
       2023-03-21 19:16:54 +08:00
    别用 revert 用 reset 回到 E
    kyonn
        12
    kyonn  
    OP
       2023-03-21 19:18:21 +08:00
    @rrfeng
    > If the upstream branch already contains a change you have made (e.g., because you mailed a patch which was applied upstream), then that commit will be skipped and warnings will be issued (if the merge backend is used). For example, running git rebase master on the following history (in which A' and A introduce the same set of changes, but have different committer information):

    https://git-scm.com/docs/git-rebase
    kyonn
        13
    kyonn  
    OP
       2023-03-21 19:19:59 +08:00
    @godpeo 这是种解决方案, 但 dev 是公共分支, 在开发期间 reset 等价于修改公共分支的历史, 有较大的风险, 因此不太想这么做.
    leonshaw
        14
    leonshaw  
       2023-03-21 19:22:07 +08:00 via Android
    不明白为什么一个 commit main 上有,dev 上不能有,合并以后又要有
    rrfeng
        15
    rrfeng  
       2023-03-21 19:23:37 +08:00
    -i 试试交互模式能保留吗?
    感觉既然 issue warning 了,应该有选项可以禁用这个特性?
    optional
        16
    optional  
       2023-03-21 19:27:19 +08:00
    再 revert 一次。。
    kyonn
        17
    kyonn  
    OP
       2023-03-21 19:28:31 +08:00
    @leonshaw 这个需求是比较奇怪, 原先最朴素的想法是这个问题在主线上的某个产品出现, 所以要求直接提 MR 给主线, 但是修改人提交的 MR TARGET branch 选错了, 变成了 dev 分支, 而 dev 分支上在开发其他产品, 跟这个 bug 没关系, 就直接 revert 了.
    注: 这个 bug 改的不是公共代码, 而是主线上某个产品分支的代码, 而这个产品分支在 dev 上不涉及, 换句话说, dev 分支上在开发其他产品.
    leonshaw
        18
    leonshaw  
       2023-03-21 19:28:44 +08:00 via Android
    @kyonn #13 其他人 pull 到 Q' 之前 force push 是安全的。
    kyonn
        19
    kyonn  
    OP
       2023-03-21 19:29:47 +08:00
    @optional .... 见我后面的补充, dev 分支存在比较久... 到 rebase 的时候不一定记得有这么个坑要填....知道有这个问题了还是比较好处理的.
    kyonn
        20
    kyonn  
    OP
       2023-03-21 19:30:39 +08:00
    @leonshaw 对的, 但因为 Q'已经在 gitlab 上了, 所以并不能保证没人 pull 到这个 commit... 为了稳妥期间, 才选择 revert 的.
    kyonn
        21
    kyonn  
    OP
       2023-03-21 19:31:22 +08:00
    @rrfeng 交互模式是有告警的... 测试了下.
    optional
        22
    optional  
       2023-03-21 19:32:08 +08:00
    @kyonn 忘了就没什么好办法。。这相当于你要在一个分支上保留特定修改,又要于其它分支交互。。
    vvdsaa
        23
    vvdsaa  
       2023-03-21 21:14:41 +08:00 via iPhone
    从 main checkout 一个新 branch 指向 Q ;
    cherrypick D 、E ;
    新 branch pr 到 main
    weyou
        24
    weyou  
       2023-03-22 01:30:06 +08:00 via Android
    关键点在于 dev 分支上的 Q 本就不该 revert 。既然 dev 是其他不相关的开发,不 revert 相当于提前 cp 了 main 的一些 commit ,Q 在 dev 上的存在是很正常的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2893 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 36ms · UTC 15:23 · PVG 23:23 · LAX 08:23 · JFK 11:23
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.