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

请教下关于 git 的工作流

  •  
  •   kyonn · 2022-11-16 18:29:10 +08:00 · 3625 次点击
    这是一个创建于 736 天前的主题,其中的信息可能已经有所发展或是发生改变。

    以前用的 svn, 大概开发模式如下:

    1. 从 trunk 分支拉出某个产品的开发分支 dev1(不同产品团队可以拉不同的 dev 分支).
    2. 所有人在 dev1 分支上提交.
    3. dev1 分支打 tag, 从 tag 出版本进行人工测试.
    4. 测试通过将 dev1 分支 merge 回 trunk, 如果有其它 dev 分支提前合回了 trunk, 则需解决冲突.

    了解过三种 git 工作流, 目前想这么做: 分支用 master 和 dev, 开发人员基于 dev 拉自己的 feature 分支, 开发完成后基于 dev 做 rebase, 然后提 MR, 审核通过后代码 merge 进入 dev 分支. 等开发完成后, 基于 dev 去出版本测试, 测试通过后再将 dev merge 回 trunk. 个人的疑问是 dev 分支如何 merge 回 master? 如果 dev 也要基于 master 做 rebase 后再提 MR, 那么就违反了公共分支不能 rebase 的原则. 如果 dev 先 merge master 解决冲突后再提交 MR, 又会导致 master 历史非常乱.

    ps: 我们的产品必须人工测试, 不能用基于主干开发的模式. 另外, 不同团队可能同时在开发不同产品, 所以用不同的 dev 分支隔离彼此是必要的.

    30 条回复    2022-11-18 20:21:10 +08:00
    mickerwx
        1
    mickerwx  
       2022-11-16 18:42:07 +08:00   ❤️ 3
    - 集中式工作流:开发者直接在本地 master 分支开发代码,开发完成后 push 到远端仓库 master 分支。
    - 功能分支工作流:开发者基于 master 分支创建一个新分支,在新分支进行开发,开发完成后合并到远端仓库 master 分支。
    - Git Flow 工作流:Git Flow 工作流为不同的分支分配一个明确的角色,并定义分支之间什么时候、如何进行交互,比较适合大型项目的开发。
    - Forking 工作流:开发者先 fork 项目到个人仓库,在个人仓库完成开发后,提交 pull request 到目标远程仓库,远程仓库 review 后,合并 pull request 到 master 分支
    kyonn
        2
    kyonn  
    OP
       2022-11-16 19:04:01 +08:00
    @mickerwx 我的需求比较像你说的 功能分支 工作流, 但是 新分支 如何合回主线, 这是我的疑问点.
    因为 git 是基于 snapshot 去管理文件的, 不像 svn 是基于 diff(差异)的, 就会导致不做 rebase 进行 merge 的 master 历史非常乱(master 历史上会有关于同一个修改的重复历史).
    如果用 squash , 又会丢失原作者的信息.
    corningsun
        3
    corningsun  
       2022-11-16 19:06:47 +08:00
    “不同团队可能同时在开发不同产品”

    你们必须要用一个分支? 能否拆分多个项目,每个项目功能都尽可能小。

    “公共分支不能 rebase 的原则”

    到 master 可以直接 merge ,没必要强制 rebase 的
    kyonn
        4
    kyonn  
    OP
       2022-11-16 19:27:10 +08:00
    @corningsun 不同团队开发可以用不同的 dev 分支, 但是开发完成要统一合回 master 分支. 这就导致第二个及之后合回 master 分支的 dev 分支肯定不能达到 fast-forward 要求, 这时候要么做 rebase, 要么做 merge, 之后才能提交 PR 给 master 分支.

    到 master 可以直接 merge ,没必要强制 rebase 的
    -- 直接 merge 的话会导致 master 历史比较乱, 比如下面这种, 不利于后续维护, 比如想要单独回退某个 feature 的修改.
    * 9f0c13b (HEAD -> master) feture-c finished
    |\
    | * 55be61c C.2
    | * e18b5c5 merge master
    | |\
    | |/
    |/|
    * | ee549c2 feture-a finished
    |\ \
    | * | 51f2126 A.3
    | * | 72118e2 merge master

    想要的是类似下面这种历史:
    v* e2e6451 (HEAD -> master) feture-c finished
    |\
    | * 516fc18 C.2
    | * 09112f5 C.1
    |/
    * c6667ab feture-a finished
    |\
    | * e64c4b6 A.2
    | * 6058323 A.1
    |/
    statumer
        5
    statumer  
       2022-11-16 20:14:52 +08:00 via iPhone
    公共分支可以 rebase onto ,只是不可以 rebase inplace 。rebase onto 并不会破坏共识。搞懂原理。
    andyJado
        6
    andyJado  
       2022-11-16 20:17:58 +08:00
    有没有考虑过 submodule 呢?
    kyonn
        7
    kyonn  
    OP
       2022-11-16 20:59:19 +08:00 via Android
    请教下,我指的是 dev rebase onto master ,这个对 dev 分支来说会破坏共识吧? dev 分支对一个项目的成员来说是公共分支。
    kyonn
        8
    kyonn  
    OP
       2022-11-16 20:59:50 +08:00 via Android
    @andyJado 这个适用于拆分功能模块吧。
    andyJado
        9
    andyJado  
       2022-11-16 21:24:51 +08:00
    @kyonn
    我的内心:
    如果你用 git 但不用 fork ,那一定是库太大了不好拉到本地吧,所以可能先拆一下主 repo 然后再 fork 吧
    kyonn
        10
    kyonn  
    OP
       2022-11-16 21:53:23 +08:00 via Android
    @andyJado 这个意思啊。github 好像用 fork 多一些,gitlab 倾向于分支。fork 的话还是会有我说的疑问,dev 如何回到 master 。
    GzhiYi
        11
    GzhiYi  
       2022-11-17 01:30:12 +08:00 via iPhone
    可以看看 github flow ,你的 dev 代码可以通过 mr 并入 master 不是么? master 代码理论只存放最新的线上环境的代码。
    GzhiYi
        12
    GzhiYi  
       2022-11-17 01:31:02 +08:00 via iPhone
    不对,可以从 master 切出 feature 分支,只维护 master 和 feature 分支就好。
    swulling
        13
    swulling  
       2022-11-17 06:41:04 +08:00
    还是建议用 主干-开发-功能分支模式,开发分支配置为线性历史

    日常提交代码在功能分支,rebase 或者 squash merge 到开发分支。

    开发分支可以有多个,在每次 merge 进 master 后立刻触发一个 git rebase master 将代码更新为最新。
    这个动作可以自动执行避免人工遗漏。

    然后所有人的 git 配置中 branch.<branchname>.rebase 设置为 true
    kyonn
        14
    kyonn  
    OP
       2022-11-17 08:11:25 +08:00 via Android
    @swulling 我理一下你的意思,帮忙看下我说的对不对。
    开发人员基于开发分支创建自己的功能分支,一旦某个 feature 完成开发后,先将功能分支 rebase onto 开发分支,然后已经 mr 给开发分支,合入后可以删除功能分支。继续从开发分支拉功能分支,继续下一个功能开发。
    等待开发分支上合入了所有特性,并且测试通过,基于开发分支直接提交一个 mr 给主干,主干审核通过后会自动触发开发分支 rebase onto 主干分支。
    kyonn
        15
    kyonn  
    OP
       2022-11-17 08:22:07 +08:00 via Android
    @swulling 自动触发 git rebase master 将代码更新为最新,是针对已经合入 master 的开发分支,还是未合入的开发分支呢?
    swulling
        16
    swulling  
       2022-11-17 08:34:57 +08:00 via iPhone
    @kyonn 针对刚刚合入的,这样保证开发分支的 history 和主干一样,而不是来回 merge
    kyonn
        17
    kyonn  
    OP
       2022-11-17 08:48:18 +08:00 via Android
    @swulling 开发分支提交 mr 给主线有冲突要怎么解决呢?先 merge 主线再提 mr ?
    kyonn
        18
    kyonn  
    OP
       2022-11-17 08:53:47 +08:00 via Android
    @swulling 开发分支合入主线后 rebase 主线会不会导致开发分支历史混乱呢?毕竟这是公共分支
    rationa1cuzz
        19
    rationa1cuzz  
       2022-11-17 09:15:04 +08:00
    要不试试主分支打 tag 的方式来管理版本问题?从 dev 往 master merge 确实会出现乱的情况,每次 rebase 的话又要处理冲突,很麻烦
    kyonn
        20
    kyonn  
    OP
       2022-11-17 09:37:17 +08:00
    @rationa1cuzz 能否详细讲讲 tag 管理版本?
    oppoic
        21
    oppoic  
       2022-11-17 09:38:25 +08:00   ❤️ 1


    老图了,参考参考,几个人开发还是怎么简单怎么来
    unco020511
        22
    unco020511  
       2022-11-17 14:55:14 +08:00
    我说说我们的,三个分支 main->dev->feature
    main 用作发布分支,当要开发一个新版本时,从 main 拉一个 dev-version,各个版本要带出的功能由开发自己拉 feature 分支,某个功能开发完成后,在 feature 分支提测,测试通过后合并入 dev-version,等待这个版本的所有 feature 合入 dev-version 后,对 dev-version 进行版本测试(主要排除多个新功能间可能引发的问题),然后将 dev 合到 main,在 main 上出 xxx 版本的发布包.
    开发下一个版本,从 main 拉新的 dev.....
    kyonn
        23
    kyonn  
    OP
       2022-11-17 15:55:23 +08:00
    @unco020511 我想的也是这个策略. 我的疑问是 dev 修改合入 main 分支出现冲突时, 如何解决该冲突.
    有两种处理策略:
    1. dev 分支先 rebase onto main, 解决完冲突后提交 MR 或者 PR 给 main 分支(dev 和 main 历史清晰, 但是 dev 历史被重写).
    2. dev 分支先 merge main 分支, 解决完冲突后提交 MR 或者 PR 给 main 分支(main 和 dev 历史会比较乱, 因为 dev 和 main 相互 merge).
    不知道你们那边是如何处理的?
    Xheart
        24
    Xheart  
       2022-11-17 16:34:10 +08:00
    @unco020511 我这也是这种流程
    statumer
        25
    statumer  
       2022-11-17 16:55:09 +08:00
    @kyonn #7 不会破坏。先创建一个临时分支指向 dev 。然后临时分支 rebase onto master 。解决冲突后,让 master 指向临时分支。

    ```
    o------o------o trunk
    \
    o---o dev

    创建临时分支 feat-pending
    o------o------o trunk
    \
    o---o dev, feat-pending

    rebase (处理冲突) 后
    trunk
    o------o------o----o'----o' feat-pending
    \
    o---o dev

    fast forward
    o------o------o----o'----o' trunk, feat-pending
    \
    o---o dev

    移除临时分支 feat-pending
    o------o------o----o'----o' trunk
    \
    o---o dev

    可以看到全程和 dev 无关。
    ```
    kyonn
        26
    kyonn  
    OP
       2022-11-17 18:02:24 +08:00
    @statumer 了解了, 相当于复制了 dev 分支, 用复制的分支去做 rebase 操作. 再请教下, master, dev, feature 倾向于用同一个仓库吗? 换句话说, 什么时候要 forking ?
    statumer
        27
    statumer  
       2022-11-17 19:06:23 +08:00
    @kyonn #26 用 gitlab 这种可以设置 protected branch 的 git 系统不需要 fork 。fork 不利于维护 single source of truth 。
    kyonn
        28
    kyonn  
    OP
       2022-11-17 20:35:03 +08:00 via Android
    @statumer 了解了,多谢
    unco020511
        29
    unco020511  
       2022-11-18 16:00:50 +08:00
    @kyonn #23 dev 合 main 是单向的怎么会有冲突呢,各个 feature 之间的冲突在 feature into dev 时就已经解决,每个 feature 自己怎么玩都可以,但在 mr 时要确保解决完冲突,且 mr 勾选 Squash commits .

    其实不管是哪种模型,原则都是差不多的:
    1. 主干都是受保护的,仅接受 mr 合并,且一般只有开发和测试 leader 有权限,mr 要求审核
    2. feature 分支各个开发随便玩,但 mr 之前要预先解决冲突,冲突要确定影响面给到测试
    3. 如果多个 feature 在同时开发中且有共用改动代码时(一般很少),采用 pick
    kyonn
        30
    kyonn  
    OP
       2022-11-18 20:21:10 +08:00
    @unco020511 多个团队同时在开发会有多条 dev, 先合入主线的 dev 不会有冲突, 但是后合入的会有冲突.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3595 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:18 · PVG 12:18 · LAX 20:18 · JFK 23:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.