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

请教下关于 git 的工作流

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

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

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

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

    到 master 可以直接 merge ,没必要强制 rebase 的
    kyonn
        4
    kyonn  
    OP
       72 天前
    @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  
       72 天前 via iPhone
    公共分支可以 rebase onto ,只是不可以 rebase inplace 。rebase onto 并不会破坏共识。搞懂原理。
    andyJado
        6
    andyJado  
       72 天前
    有没有考虑过 submodule 呢?
    kyonn
        7
    kyonn  
    OP
       72 天前 via Android
    请教下,我指的是 dev rebase onto master ,这个对 dev 分支来说会破坏共识吧? dev 分支对一个项目的成员来说是公共分支。
    kyonn
        8
    kyonn  
    OP
       72 天前 via Android
    @andyJado 这个适用于拆分功能模块吧。
    andyJado
        9
    andyJado  
       72 天前
    @kyonn
    我的内心:
    如果你用 git 但不用 fork ,那一定是库太大了不好拉到本地吧,所以可能先拆一下主 repo 然后再 fork 吧
    kyonn
        10
    kyonn  
    OP
       72 天前 via Android
    @andyJado 这个意思啊。github 好像用 fork 多一些,gitlab 倾向于分支。fork 的话还是会有我说的疑问,dev 如何回到 master 。
    GzhiYi
        11
    GzhiYi  
       72 天前 via iPhone
    可以看看 github flow ,你的 dev 代码可以通过 mr 并入 master 不是么? master 代码理论只存放最新的线上环境的代码。
    GzhiYi
        12
    GzhiYi  
       72 天前 via iPhone
    不对,可以从 master 切出 feature 分支,只维护 master 和 feature 分支就好。
    swulling
        13
    swulling  
       72 天前
    还是建议用 主干-开发-功能分支模式,开发分支配置为线性历史

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

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

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


    老图了,参考参考,几个人开发还是怎么简单怎么来
    unco020511
        22
    unco020511  
       71 天前
    我说说我们的,三个分支 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
       71 天前
    @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  
       71 天前
    @unco020511 我这也是这种流程
    statumer
        25
    statumer  
       71 天前
    @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
       71 天前
    @statumer 了解了, 相当于复制了 dev 分支, 用复制的分支去做 rebase 操作. 再请教下, master, dev, feature 倾向于用同一个仓库吗? 换句话说, 什么时候要 forking ?
    statumer
        27
    statumer  
       71 天前
    @kyonn #26 用 gitlab 这种可以设置 protected branch 的 git 系统不需要 fork 。fork 不利于维护 single source of truth 。
    kyonn
        28
    kyonn  
    OP
       71 天前 via Android
    @statumer 了解了,多谢
    unco020511
        29
    unco020511  
       70 天前
    @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
       70 天前
    @unco020511 多个团队同时在开发会有多条 dev, 先合入主线的 dev 不会有冲突, 但是后合入的会有冲突.
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   1676 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 42ms · UTC 01:09 · PVG 09:09 · LAX 17:09 · JFK 20:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.