git工作流实践
这是一篇在我个人工作实践中,在我参与的,负责的项目、团队协作中,逐步调整,适合于一些实际场景的 git 工作流实践。
众所周知,在软件开发中, git 是目前使用最广泛的 软件版本管理工具,它足够高效,足够安全,也足够灵活, 对于团队协作和软件管理提供了很大的帮助。
而一个良好的合适的 分支管理方案,可以更好的帮助我们通过 git 进行 软件版本管理。
在过去, git-flow 是一个很流行的 分支管理方案。对于多人协作,中大型项目,提供了一个较为满意的解决方案。
但在我过去的实践中,逐渐感受到 git-flow 对于我来说还是太过于繁杂了,虽然在事实上满足了 我对于项目的软件版本管理, 但认为还是可以做一些简化,调整 分支管理策略,以更好的适配实际的开发工作。
场景
试想一下,在我们实际的软件开发过程中,迭代一个软件的版本,正常来说是:
需求评审 -> 需求确认 -> 开发阶段 ->
测试环境测试 -> 预生产发布验证 -> 生产环境发布验证 -> 发布完成
从开发到发布
在这个过程中,如果在 测试环境发现了 bug,需要重新回归到 开发阶段进行修复, 同样的,在预生产发布验证环节发现了问题,也需要重新回归到 开发阶段修复后,重新测试和发布预生产。
而如果 生产环境发布验证 出现了问题, 需要紧急回滚到上一个版本,并重新回到开发阶段修复,测试,预生产验证,再生产发布。
需求明确 or 变更
虽然我们一直强调,版本迭代进入开发后,这个版本的需求应该是明确的。
然而,这仅仅只是理想情况下,实际过程中经常会遇到 需求变更,甚至是 添加新的功能,删除功能等。 这种变更,还很难控制会发生在开发阶段还是测试阶段。
也许我们会吐槽甚至抱怨这样的容易变更需求的项目管理很糟糕,很不专业。但是,这也是确确实实存在的场景, 即使再成熟的团队,也会不可避免的遇到这种问题。
然而需求变更也不代表着一定是上面这种场景。
周期性版本发布,需求池
有些项目可能相对来说比较成熟,或者采用了不同的版本迭代方式。
周期性版本发布指,采用某个固定的周期内,仅会也一定会发布一个版本,如 每两周发布一个版本。 那么在这种模式下,每个版本上线哪些功能,上线多少功能,实际上是以各个功能的开发进度,和进入到当前周期后, 明确下来的版本计划再决定的。
将产品 明确划分为一个个需求,建立一个需求池,并指定了每个需求的按时间的线性迭代预期计划, 在预期的未来的周期性的版本发布中,会上线哪些需求功能。
在这种场景下,我们不可能把需求都集中在某个分支上进行开发,仅有的一个 develop分支也很难满足所有的 开发合并和测试。
开发人员对于 git的掌握
很多时候,对于工具能够使用到什么程度,对于项目能够有多少帮助,其实不在于 工具有多优秀,而是在于团队成员 对于工具的平均掌握程度,已经是否有成熟的规范化的操作流程。
早期我认为 成员对于 git 的掌握是大差不差的,只要说明一些操作流程即可,未加以限制和规范
然而,这会也给项目带来了潜在的风险:主要分支可能会被误操作污染,多个功能直接在同一个分支开发等等。
而为了解决这些问题,需要建立一套足够完善,同时低复杂度的操作规范,并对人员和分支加以权限控制。
分支管理实践
在以上的场景中,逐渐摸索出了一套合适的分支管理方案:
master
分支: 主分支,正式版本的代码提交记录。永远不会在上面做任何改动提交,也仅接受来自
release
分支的合并请求,合并后打上版本tag。release
分支:发布分支,用于发布版本到预生产和生产环境,发布完成后合并到 master分支。永远不会咋上面做任何改动提交,也仅接受来自 prerelease 分支的合并请求。
prerelease/*
分支组: 预发布分支,根据版本号创建新的分支。仅合并当前版本关联的
feature/*
分支,用于合并开发完成的需求,进入到版本测试阶段,发布到测试环境。 不会或者尽可能少的在上面做任何改动提交。feature/*
分支组: 功能开发分支(包括hotfix),从 master 分支拉取创建的分支,每个分支仅针对某一个单一的业务或者功能,所有的改动都应该在 feature 分支上进行。 仅能合并到 prerelease 分支。 master有更新后需要及时拉取合并同步。
流程图:
可以看出,整个方案只有四条主要的分支,且不同功能分支到其他分支都是单向的。
这样的好处是足够的简单,足够的好理解,也保证了一定的灵活性。
删除了 develop分支的原因是,单一的develop分支并不能很好的满足 需求变更后导致的 develop分支无效, 选择使用 prerelease 分支组作为替代,可以灵活的根据版本规划创建分支,即使发生需求变更,也可以灵活的直接抛弃 当前已创建的分支,重新新建一条 prerelease分支再次从feature分支合并代码。
从 develop 改名为 prerelease 也是因为,功能分支开发完后并不是马上合并的,而是根据迭代计划再合并的,理解起来就是 预期上线的功能,即 prerelease。
从分支的行为上看, master分支和 release分支 似乎可以在简化仅保留一条。但这里是考虑到 如果有发布回滚操作,如果 都在 master 分支上进行,那么master分支的操作记录看起来就不够的干净,简洁,而把发布、回滚等策略都放到了 release分支 ,而 master仅保留干净的版本历史,那么会更加的友好,便于维护。
在这个方案中,最好是配合上 git分支的权限控制,对 master分支、release分支进行保护,确保这两个分支仅接受来自对应 分支的合并请求。
分支合并,选择 merge
还是 rebase
,这个需要对 commit记录有何要求去考量。 如果需要保证所有提交记录都可追踪,建议使用 merge,如果希望 提交记录线性、整洁,建议使用 rebase。
同时,feature分支 合并到 prerelease 分支,最好是通过 pull requests 的操作模式,在进入测试阶段前,接受来自其他 有用审查权限的开发人员的code review。
说明
该实践方案仅是我过去在我的工作实践中总结的,并在团队内部经历过超过2年的验证和调整所得出的,适合于当时团队的实践方案。
是否与您的团队或所在的团队契合,还需要重新考量。
分支管理方案 需要从实际的情况触发考虑,包括团队人数,产品规模等等。
没有最好的方案,只有合适自己的方案。