V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
git
Pro Git
Atlassian Git Tutorial
Pro Git 简体中文翻译
GitX
abcbuzhiming
V2EX  ›  git

请教关于 git 的分支合并的最佳实践,多人协作时 hotfix 该如何处理?

  •  1
     
  •   abcbuzhiming · 2021-04-26 14:50:35 +08:00 · 3762 次点击
    这是一个创建于 1334 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在看 git 合并策略的文章时注意到了一个案例,dev 分支上加入了一个 A 文件,然后合并给了 main 分支。dev 分支继续向前开发。此时 main 分支发现新加入的 A 文件有 bug,于是紧急 fix,撤掉了合并,并生成一个新的 commit 。。此时 dev 在向前推进了一个 commit,然后此时 dev 再次合并到 main,合并后发现 main 内部“丢失”了 A 文件。

    那篇文章解释这个现象是“三向合并”导致的,因为,因为 main 撤销合并时,实际对 A 文件做了删除,而 dev 分支直到第二次合并时对 A 没有任何改变,所以这个"对 A 改变"的行为在版本上说是最新的,于是合并后,A 就被删除了。

    这个问题让我产生的疑问是:
    *.按这个理解,最好不要在 main 分支上直接做任何改动?
    *.但是如果我要 hotfix 的时候,该怎么操作呢?难道 hotfix 的改动需要通知到 dev 去?也就是 hotfix 合并到 dev,那如果人多一点,同时有十几个个 dev 分支在开发,一个 hotfix 就要发十几次次合并?
    *.而且,像上面这文里提到的,hotfix 需要删除文件,把 hotfix 合并到 dev,肯定会导致 dev 的文件也被删掉,这是不是有点不妥?
    16 条回复    2021-04-26 20:24:26 +08:00
    yiXu
        1
    yiXu  
       2021-04-26 14:57:42 +08:00   ❤️ 3
    1. 如果 main 需要删除 A 文件,应该从 main 分支分出 一个 delete-A 的分支,提交删除 A 文件的 commit,然后合并到 main 分支。
    2. 如果 dev 分支与 main 分支有冲突,应该先 merge main 分支到 dev 分支,然后解决冲突,再将不会与 main 分支冲突的功能完善的 dev 分支 merge 进入 main 分支。

    个人的操作是这样的。
    janxin
        2
    janxin  
       2021-04-26 15:44:28 +08:00   ❤️ 1
    以 git-flow 实践为例,git-flow 提供一个特定的 “hotfix” 工作流程:

    https://www.git-tower.com/learn/git/ebook/cn/command-line/advanced-topics/git-flow/#hotfix
    janus77
        3
    janus77  
       2021-04-26 16:42:35 +08:00
    main 分支不要改动
    你说的情况,正确办法应该是这样的:main 拉一个新分支做 hotfix,该分支删掉 A 文件。然后先合到 dev 分支上去,再从 dev 合到 main 。
    针对你的多个 dev 分支,这里应该有一个主 dev 分支的情况,各自开发的时候从主 dev 拉出子 dev 。子 dev 开发完成以后要合并到主 dev,此时需要先从主 dev 反合到子 dev,再从子 dev 合到主 dev,这是防止上面所说的冲突。另外主 dev 是长期存在的,子 dev 在本期开发完成以后就可以删掉了。
    zhengxiaowai
        4
    zhengxiaowai  
       2021-04-26 17:10:52 +08:00
    既然都是 hotfix 肯定不会管你开发分支了,此时针对 master 再提交一个 commit 即可,没太理解撤掉合并是什么意思? revert 也是产生一个单独的 commit

    此时 master 分支比 dev 分支多了一个 commit,dev 分支只需要 rebase 一下 master 即可,如果不去 rebase 一下 dev 分支下次提 merge request 时候会冲突,修改冲突即可。
    abcbuzhiming
        5
    abcbuzhiming  
    OP
       2021-04-26 17:13:14 +08:00
    @janus77
    正确办法应该是这样的:main 拉一个新分支做 hotfix,该分支删掉 A 文件。然后先合到 dev 分支上去,再从 dev 合到 main
    ======
    我的疑惑在这里,hotfix 删除 A 文件,再合并到 dev 分支上,这么干是否会导致 dev 分支的 A 文件被删掉?我觉得应该是会的,也就是说 dev 分支将不得不在合并后想办法去“找回”A 文件,这个体验似乎,有点糟糕?
    rosia
        6
    rosia  
       2021-04-26 17:16:52 +08:00
    这头像。。。
    abcbuzhiming
        7
    abcbuzhiming  
    OP
       2021-04-26 17:40:35 +08:00
    @zhengxiaowai 那篇文章显然是为了故意造成这个效果,才做这样的场景操作的,
    不过你提到的场景我也不太理解,为什么:
    master 分支比 dev 分支多了一个 commit,再和 main 分支 merge request 的时候就会报冲突?这个冲突的原因是什么?是因为 git 找不到合并需要的 base 节点了吗?
    brader
        8
    brader  
       2021-04-26 17:47:45 +08:00
    我们可以从优秀的项目身上借鉴经验,让我们来看一个案例,前段时间( 4 月 15 日),以太坊柏林硬分叉,openethereum 节点进行 Berlin hotfix 的一个案例:

    - https://github.com/openethereum/openethereum/pull/366

    - https://github.com/openethereum/openethereum/commits/dev

    我们观看上面两个链接的 git 工作流,可以看到他的 hotfix 流程大致是这样的:

    - Merge branch 'berlin_hotfix' into release/v3.2.1
    - Merge branch 'release/v3.2.x' into main
    - Merge branch 'main' into dev

    从这里相信你能看出,当出现一个紧急严重的 bug 的时候,你首先应该做的是第一时间、最短时间解决线上的漏洞,抛开一切繁琐的影响你解决问题的因素(不要再去想其他分支的事情了,你已经没有时间了)。

    你首先应该从当前发布版本切出一个 hotfix 分支,修复后,第一时间将该修补提交合并到新的发布版本,这时候你已经完成了你最应该做的,最紧急的事情,接下来,你就可以按部就班的,逐步将该修复合并到其他分支。


    当然,我们现实项目中,可能少了像开源项目有发布版本这个 tag,我们的线上可能就是 master 分支,但是原理是一样的。
    brader
        9
    brader  
       2021-04-26 17:57:44 +08:00
    这里我再补充一点,只有非常紧急的 BUG,才走上面的一个流程。
    正常修复普通不紧急的 BUG,个人建议最好还是走平时的正常流程(开分支->修复->测试->上线)。
    git 是鼓励你频繁创建分支以及删除分支的,因为你线上使用的总是 master 分支,所以你的其他分支是无需合并本次 bug 修复的,因为该分支在开发完,就会被你删除,而后的新东西,你总是从 master 切个新分支出来。

    或者你还有一个持久存在的 dev 分支,那么你的 dev 分支,应该总是不定时的从 master 分支获得修复反哺。
    xuanbg
        10
    xuanbg  
       2021-04-26 17:59:11 +08:00
    hotfix 是对已发布的 branch/tag 的 commit 进行修复。所以,测试通过后应该 Merge 到所有基于该 commit 的 branch 。
    abcbuzhiming
        11
    abcbuzhiming  
    OP
       2021-04-26 18:01:51 +08:00
    @brader 目前大家说的流程我已经非常清晰了,只是这还是没有解决我说的那个疑问

    我在 hotfix 为了修复暂时删除了 A 文件,我肯定需要把 Hotfix 合并到 dev 上去的,此时 dev 上的 A 文件是不是会被删掉?按照顶楼说的那个场景:会,因为 hotfix 对 A 文件做的修改,在版本线路上比 dev 新。那么这就会造成 dev 在合并进来 hotfix 后,不得不重新去找回 A 文件,这个流程总觉得有点别扭
    janus77
        12
    janus77  
       2021-04-26 18:09:34 +08:00
    @abcbuzhiming #5 如果没有发生冲突,那么你说的体验问题是不存在的。git 系统不是人类,对他来说 add 和 delete 是同一个级别的操作,没有好与坏之分
    SureE
        13
    SureE  
       2021-04-26 18:10:22 +08:00
    推荐一篇文章
    Martin Fowler 的 https://martinfowler.com/articles/branching-patterns.html
    讨论了多种不同的分支管理模型,以及各自的优劣。
    brader
        14
    brader  
       2021-04-26 18:12:36 +08:00
    @abcbuzhiming 会删除 A 文件的,这是完全没有问题的,因为你自己说了,你解决 hotfix 的办法就是删除了 A 文件。那么 A 文件的存在就是一个 BUG,所以你希望的 dev 分支也解决掉这个 BUG,那你就是要删除了 A 文件,如果说,不删除 A 文件也能解决 BUG,那么就说明你前面为了解决 BUG 而删除 A 文件的行为不是最优解。
    ThanksSirAlex
        15
    ThanksSirAlex  
       2021-04-26 19:25:41 +08:00
    现在很多主流的 git flow 都不用 develop 分支了,只有 main 和需求分支,github flow 和 gitlab flow,都没有 develop 这个概念了,实际中 develop 分支的意义确实也不大
    yiXu
        16
    yiXu  
       2021-04-26 20:24:26 +08:00   ❤️ 1
    @abcbuzhiming 个人实际测试了一下。

    1. 如果你的 A 文件在 dev 分支中没有任何修改。而 main 分支的热修复删除了 A 文件,当 dev 分支 merge main 分支则会删除 A 文件。

    2. 如果你的 B 文件在 dev 分支中有修改。而 main 分支的热修复删除了 B 文件,当 dev 分支 merge main 分支则会发生自动合并失败,而 B 文件则会显示冲突,需要自行在文件中解决冲突。并重新提交这个 commit,完成 merge 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1113 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 18:37 · PVG 02:37 · LAX 10:37 · JFK 13:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.