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

这样的 git commit history 还有得救么?

  •  
  •   AntiGameZ · 64 天前 · 1019 次点击
    这是一个创建于 64 天前的主题,其中的信息可能已经有所发展或是发生改变。

    工作仓库,就叫做 repo 吧。平时大家都是通过 pull request 合并代码。每个 pull request 都会 squash merge 。

    几个月前开了个 feature branch,是给新平台重构用的,就叫做 branchNew 吧。

    本来的计划是,每周从 master 分支把新修改同步到 branchNew,这样开发的人继续在 master 上工作,新平台的工作人员在 branchNew 上工作,等要切换的时候,直接用 branchNew 换掉 master 。

    因为所谓的"新平台"其实是从一个云服务商换到另外一个云服务商,所以业务代码变动很小,都是一些和 infra 联系紧密的东西,一直以来相安无事。

    这事儿本来不归我管,今天发现 branchNew 发布出来的代码出了很奇怪的问题。看了下发现问题大了。然后发现做同步的老哥 X 是这么干的

    • 假设这周有 10 个 pull request 合并到 master
    • 老哥从 branchNew 开了个新分支 branchNew-for-merge
    • 合并来自 master 的 10 个新 commit
    • 创建一个新 pull request,从 branchNew-for-merge 到 branchNew
    • 然后 squash merge !!!!没错,squash merge

    这样一来,随着时间推移,branchNew 上的代码慢慢都变成老哥 X 写的了。这还没啥。但是发现会出现即便没有 conflict,但是较老的代码覆盖了较新的代码。

    原理我没大搞明白

    • 因为 master 上代码都是一个 PR 对应一个 commit
    • 合并分支每周都做。所以 branchNew 上进来的 master 代码都是新代码
    • 没有 conflict

    感觉怎么样都是应该新的 commit 会进来,没道理有老的修改去覆盖新修改的事情。因为 commit 的时间线决定了 commit 在时间上的顺序性。

    不过无论如果目前的做法是不对了,老哥 X 这样同步已经做了几个月。现在除了砍掉重新同步以外,还有救吗。

    5 条回复    2021-09-26 01:38:44 +08:00
    Pipecraft
        1
    Pipecraft   64 天前
    肯定还有救。就看你想要的结果是什么样子的了。

    branchNew 上的修改结束了吗?修改内容代码变动很小对吧?
    如果是的话,应该把 branchNew 上的修改 squash merge 成一个 commit,然后和 master 的历史记录合起来。
    如果以后不用 master 分支,要切换到新的分支作为主干( branchNew 看来不能作为主干了),
    可以先从 master 分支复制出一份分支,叫 main 。
    然后把 branchNew 分支 squash merge 到 main,这样这位老哥 X 写的代码会变成一个 commit 在 main 分支的历史记录里。branchNew 现在已经有 master 的新代码也没关系,没有过 conflict,所以和 main 合并时不会有问题。
    以后新平台的开发在 main 分支开新分支修改,然后再 squash merge 到 main 。
    msg7086
        2
    msg7086   64 天前
    换个懂 Git 的人来重做一下历史吧……
    AntiGameZ
        3
    AntiGameZ   64 天前
    @Pipecraft branchNew 修改还没结束,估计还得持续 1 个月样子。所以这就比较麻烦了。

    我现在倾向于:
    branchNew 不要了。因为只属于 branchNew 的修改不多,可以单独提出来。重新从 main 开个 branchGood 出来。然后把只属于 branchNew 的 change cherry pick 进去

    但是是第一次碰到这种情况,实在是头大,感觉怎么做都是奇奇怪怪的。而且也不大明白为什么会出现没有 conflict,自动 merge 选择用老代码覆盖了更新的修改。
    passerbytiny
        4
    passerbytiny   64 天前 via Android
    压缩合并是会丢失历史记录的,你这个 branchNew 压缩合并一次,就丢失它背后 master 上的 PR 记录,经过这么多次压缩合并,已经跟 master 没有任何关系了。

    时间太长,完全没救了。你只能删除了 branchNew 分支然后通过本地文件比较再建一个新的分支来折中修补,这会丢失之前 branchNew 分支自身的所有历史记录。

    压缩合并跟 SVN 提交是一样的,是单分支新提交而不是对分支合并,压根不存在冲突问题(请注意 SVN 的冲突发生在更新时而不是提交时),自然会产生代码覆盖问题。

    压缩合并是处于兼容原因才留下的合并方式,非兼容原因应当禁止使用。要保持线性提交历史,可以采用变基合并。
    AntiGameZ
        5
    AntiGameZ   63 天前
    @passerbytiny 解释的好,受教了。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2163 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 15:22 · PVG 23:22 · LAX 07:22 · JFK 10:22
    ♥ Do have faith in what you're doing.