以前用的 svn, 大概开发模式如下:
了解过三种 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 分支隔离彼此是必要的.
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 分支 |
2
kyonn OP @mickerwx 我的需求比较像你说的 功能分支 工作流, 但是 新分支 如何合回主线, 这是我的疑问点.
因为 git 是基于 snapshot 去管理文件的, 不像 svn 是基于 diff(差异)的, 就会导致不做 rebase 进行 merge 的 master 历史非常乱(master 历史上会有关于同一个修改的重复历史). 如果用 squash , 又会丢失原作者的信息. |
3
corningsun 2022-11-16 19:06:47 +08:00
“不同团队可能同时在开发不同产品”
你们必须要用一个分支? 能否拆分多个项目,每个项目功能都尽可能小。 “公共分支不能 rebase 的原则” 到 master 可以直接 merge ,没必要强制 rebase 的 |
4
kyonn OP @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 |/ |
5
statumer 2022-11-16 20:14:52 +08:00 via iPhone
公共分支可以 rebase onto ,只是不可以 rebase inplace 。rebase onto 并不会破坏共识。搞懂原理。
|
6
andyJado 2022-11-16 20:17:58 +08:00
有没有考虑过 submodule 呢?
|
7
kyonn OP 请教下,我指的是 dev rebase onto master ,这个对 dev 分支来说会破坏共识吧? dev 分支对一个项目的成员来说是公共分支。
|
9
andyJado 2022-11-16 21:24:51 +08:00
|
10
kyonn OP @andyJado 这个意思啊。github 好像用 fork 多一些,gitlab 倾向于分支。fork 的话还是会有我说的疑问,dev 如何回到 master 。
|
11
GzhiYi 2022-11-17 01:30:12 +08:00 via iPhone
可以看看 github flow ,你的 dev 代码可以通过 mr 并入 master 不是么? master 代码理论只存放最新的线上环境的代码。
|
12
GzhiYi 2022-11-17 01:31:02 +08:00 via iPhone
不对,可以从 master 切出 feature 分支,只维护 master 和 feature 分支就好。
|
13
swulling 2022-11-17 06:41:04 +08:00
还是建议用 主干-开发-功能分支模式,开发分支配置为线性历史
日常提交代码在功能分支,rebase 或者 squash merge 到开发分支。 开发分支可以有多个,在每次 merge 进 master 后立刻触发一个 git rebase master 将代码更新为最新。 这个动作可以自动执行避免人工遗漏。 然后所有人的 git 配置中 branch.<branchname>.rebase 设置为 true |
14
kyonn OP @swulling 我理一下你的意思,帮忙看下我说的对不对。
开发人员基于开发分支创建自己的功能分支,一旦某个 feature 完成开发后,先将功能分支 rebase onto 开发分支,然后已经 mr 给开发分支,合入后可以删除功能分支。继续从开发分支拉功能分支,继续下一个功能开发。 等待开发分支上合入了所有特性,并且测试通过,基于开发分支直接提交一个 mr 给主干,主干审核通过后会自动触发开发分支 rebase onto 主干分支。 |
15
kyonn OP @swulling 自动触发 git rebase master 将代码更新为最新,是针对已经合入 master 的开发分支,还是未合入的开发分支呢?
|
16
swulling 2022-11-17 08:34:57 +08:00 via iPhone
@kyonn 针对刚刚合入的,这样保证开发分支的 history 和主干一样,而不是来回 merge
|
17
kyonn OP @swulling 开发分支提交 mr 给主线有冲突要怎么解决呢?先 merge 主线再提 mr ?
|
18
kyonn OP @swulling 开发分支合入主线后 rebase 主线会不会导致开发分支历史混乱呢?毕竟这是公共分支
|
19
rationa1cuzz 2022-11-17 09:15:04 +08:00
要不试试主分支打 tag 的方式来管理版本问题?从 dev 往 master merge 确实会出现乱的情况,每次 rebase 的话又要处理冲突,很麻烦
|
20
kyonn OP @rationa1cuzz 能否详细讲讲 tag 管理版本?
|
21
oppoic 2022-11-17 09:38:25 +08:00 1
|
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..... |
23
kyonn OP @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). 不知道你们那边是如何处理的? |
24
Xheart 2022-11-17 16:34:10 +08:00
@unco020511 我这也是这种流程
|
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 无关。 ``` |
26
kyonn OP @statumer 了解了, 相当于复制了 dev 分支, 用复制的分支去做 rebase 操作. 再请教下, master, dev, feature 倾向于用同一个仓库吗? 换句话说, 什么时候要 forking ?
|
27
statumer 2022-11-17 19:06:23 +08:00
@kyonn #26 用 gitlab 这种可以设置 protected branch 的 git 系统不需要 fork 。fork 不利于维护 single source of truth 。
|
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 |
30
kyonn OP @unco020511 多个团队同时在开发会有多条 dev, 先合入主线的 dev 不会有冲突, 但是后合入的会有冲突.
|