引言
在现代软件开发中,随着工程项目规模的扩大和团队协作的复杂化,如何有效管理代码库和版本控制成为了开发者关注的焦点。传统的多库管理模式逐渐暴露出一些问题,例如:不同仓库间代码同步困难、依赖版本不一致、跨项目协作效率低下等。为了解决这些问题,越来越多的团队开始采用 Monorepo 架构,集中管理多个工程项目和共享组件,简化了代码共享和协作流程。
然而,随着 Monorepo 的普及,新的挑战也随之而来,尤其在 Git 工作流的选择与适配方面。如何在多人协作、版本管理、发布策略和持续集成等环节保持高效与一致性,是开发团队和工程师们共同面对的难题。
本文将通过对 Git 工作流在 Monorepo 环境下的探索与分析,帮助读者理解如何在该架构下选择合适的工作流,优化开发效率,并解决版本管理和协作的常见挑战。
当前开发流程及问题
当前的开发流程主要涉及三处:上游仓库(upstream
)、从 upstream
fork 出的远程仓库(own
)、以及本机仓库(local
)。当项目需要迭代开发或修复缺陷时,通常遵循以下步骤:
- 在
upstream
新建目标分支,并在local
中 checkout。 - 开发完成并准备提交测试时,将分支推送到
own
仓库。 - 在
own
仓库中发起合并请求(MR)至upstream
的目标分支。 - MR 通过后,CI/CD 选择对应分支进行测试。
- 测试通过后,将镜像推送到制品库,并自动生成标签(
tag
)。
这个流程存在几个问题:
upstream
中的目标分支没有及时合并到main
分支,随着多个开发迭代,upstream
会积累大量未合并的版本,main 分支仍停留在初始状态。- 当某个开发者修复了公共部分的缺陷,并将代码合并到目标分支时,其他开发者的新目标分支并未包含该修复,导致公共部分的缺陷依然存在。公共部分被多版本化后,失去了其作为“公共”的意义。
Git工作流
为了解决上述问题,我们探索了几种常用的 Git 工作流。
Git Flow
Git Flow 是一种经典且流程相对复杂的工作流,适用于长期维护的大型项目。由 Vincent Driessen 提出,基于分支功能和发布周期的划分设计。它的特点在于多个分支分别处理开发、测试和发布阶段,主要涉及main
、develop
、feature
、release
和hotfix
等分支。
Git Flow 的工作流程如下:
main
分支是用于生产环境的分支。它在项目开始时创建,并在整个生命周期中一直保持下去。main
分支上特定的tag
标记了不同的版本。来自其它分支的代码只有经过全面测试后才能合并到main
分支中,不能直接修改。develop
分支也是在项目开始时创建,并在整个开发过程中进行维护,包含了正在开发的新功能,是一个预生产代码。新创建的功能应基于develop
分支。feature
分支主要用来开发一个新功能,开发完成后需要合并到develop
。release
分支用于测试环境,当develop
分支开发完成后,将develop
分支合并到release
分支提测,测试中的bug在release
分支中修复,修复通过后,将release
分支合并到main
和develop
分支中。hotfix
分支功能可快速修改main
分支中发现的问题,直接从main
分支创建,修复完成后合并回main
分支和develop
分支。合并可确保修复程序将包含在将来的发行版中,从而防止该问题再次出现。
Git Flow 的主要问题包括:
- 存在过多的分支切换操作,对于实践持续交付的团队来说效率较低。
- 强制开发者使用
develop
分支,而main
分支与其内容基本相同,导致不必要的维护成本。 - 各开发者在独立分支中工作,最后阶段合并回
develop
时容易产生冲突,增加了合并错误的风险。
GitHub Flow
GitHub Flow 是 GitHub 推广的一种轻量级工作流,专注于简单快速的交付。其核心理念是只有一个长期存在的 main
分支,没有复杂的分支模型,特别适合持续集成和快速部署的项目。
GitHub Flow 的工作流程如下:
- 基于
main
分支新创建功能分支,做开发测试工作 - 发起PR,团队成员进行代码审查、讨论并提出建议
- PR通过后,功能分支合并入
main
分支 - GitHub Flow鼓励每次合并入
main
分支后自动部署代码
虽然 GitHub Flow 流程极其简洁,但它在某些情况下并不适用:
- 被合入
main
的代码需要严格测试,而通过 PR 的代码可能还有潜在问题,但没有进一步测试机会。 - GitHub Flow 默认每次合并后自动部署,但在实际场景中,部署可能有窗口期限制。
GitLab Flow
GitLab Flow 是 GitLab 提出的工作流,旨在简化 Git Flow,同时支持持续集成和部署。它结合了 Git Flow 和 GitHub Flow 的优势,并增加了对不同环境的分支管理支持,特别适合生产部署。
GitLab Flow开始时只有三个分支:main
、pre-production
、production
,可以对应成研发环境、测试环境、生产环境。这三个分支均为受保护分支,开发者不允许直接提交到这些分支。
GitLab Flow的工作流程如下:
- 基于
main
分支新建功能分支,做开发测试工作 - 开发结束后,向
main
分支提MR - MR通过后,
main
分支的代码被合并到pre-production
分支,同时构建项目、运行测试 - 测试通过后,
pre-production
分支代码被合并到production
分支,再运行测试,然后部署到生产环境 - 在
production
分支上打tag
,同时删除功能分支
当需要hotfix
时,GitLab Flow工作流程如下:
- 基于
production
分支新建急修分支 - 开发完成后,向
main
分支提MR - MR通过且
main
分支测试通过后,因为是紧急修复,所以不能像前面流程那样一层一层的合并,而是将急修分支直接merge到pre-production
和production
分支 - 在
production
分支打tag
,删除急修分支
GitLab Flow为不同环境设置了相应的分支,这种方式在多环境管理上导致了一定的复杂性。在多人协作场景下,多个开发人员往往在同一个环境上进行开发和测试,分支合并、冲突处理、测试顺序上可能会变得比较棘手。
分支工作流探索
结合GitHub Flow和GitLab Flow的优点,同时减少环境分支的数量,本文提出一种新的工作流方式,upstream
仅长期存在main
分支,对应着生产环境。该分支为受保护分支,开发者不允许直接提交到这个分支。
以下是该工作流的工作流程:
- 基于
upstream
的main
分支创建一个功能分支,做开发测试工作 - 在
own
和local
下checkout该功能分支 - 功能开发完成,准备提测时,push到
own
下的功能分支,own
功能分支合并到upstream
下的功能分支 - CICD使用
upstream
下的功能分支做测试域部署 - 测试环境检查出的缺陷在
local
下的分支中修复,然后推送到own
下的功能分支,own
功能分支合并到upstream
下的功能分支 - 测试通过后,
upstream
的功能分支向main
分支提MR - MR通过时在
main
分支上打tag
,删除upstream
下的功能分支;MR被驳回时,提交者重新修改代码,重新向main
分支提MR - 为保证monorepo公共部分的版本唯一性,对
upstream
下长时间未删除的其它分支做统一清理
当需要hotfix
时,工作流程如下:
- 基于
upstream
的main
分支创建一个急修分支 - 开发完成后向
main
分支提MR - MR通过后,使用
main
分支部署到现网环境并测试验证。验证通过后基于main
分支打tag
,删除急修分支。
与GitLab Flow类似,该工作流也暗含了三个环境:local
和own
下的功能分支可以理解为开发环境;upstream
下的功能分支用于CICD在测试域的部署,可以理解成测试环境;main
分支只接收最终测试通过的版本,可以理解成生产环境。但与GitLab Flow不同的是,该工作流利用现有的开发流程,减少了显示的环境分支的管理,同时兼有GitLab Flow的灵活性。
该工作流的缺点在于,经过MR合并后main
分支没有测试保证,其问题的暴露时机要等到下次开发的自测和测试阶段。
总结
总结来说,monorepo 环境下的 Git 分支管理在面对多个产品、共享代码和并行开发时充满挑战。我们通过分析 git-flow、GitHub Flow 和 GitLab Flow,发现它们各自的优点与局限性。在此基础上,我们提出了一种更适合 monorepo 场景的分支管理方式,兼顾了灵活性和规范化。未来,随着团队协作的不断发展,分支管理方案将继续优化,以更好地满足复杂的企业级工程项目需求。
-END-
我们是移动云数据库前端设计团队
以创造、进取、开放为理念,发挥专业能量,创造极致用户体验
我们需要您的点赞评论和分享,也欢迎您私信后台投稿✌️