第12章:单repo多分支工作流

考虑如下场景:开发一个中型、小型或者微型微服务系统,包含10个组件

方案1:(多repo)创建10个git repo,每个repo一个master一个dev

方案2:(单repo单分支)创建1个git repo,设一个master一个dev

方案3:(单repo多分支)创建1个git repo,弃用master,每个组件单设自己的master和dev等等

方案1

方案2

方案3

环境配置简易程度

--------

++++++++

---

空间独立(同时修改不同组件是否可行)

++++++++

--------

++++++++

时间对齐(组件版本是否能够统一)

--------

++++++++

+++++

组件之间可以互相参照

--------

++++++

++++++++

添加删除组件是否方便

++++++++

--------

+++++++

由此可见,微型项目方案2最优,小型和中型项目方案3最优。 方案3可能存在的问题是:

  • 时间对齐无法实现:不存在的,参考下文

  • 需要频繁checkout:不存在的,参考下文

  • 单个git库过大:不存在的,我已经假设了是中小型系统

单repo多分支工作流的分支设置

对于小型项目,推荐按以下方式配置分支:

  • doc

    • 全部系统设计文档

  • master

    • 通过merge componentX整合系统各个部分

  • component1

    • 通过merge doc取得与之相关的部分设计文档

  • component2

    • 通过merge doc取得与之相关的部分设计文档

  • component3

    • 通过merge doc取得与之相关的部分设计文档

  • component4

    • 通过merge doc取得与之相关的部分设计文档

  • ...

对于中型项目,推荐按以下方式配置分支:

  • doc

    • 系统总体设计文档,组件接口文档

  • master

    • 在测试稳定后,merge dev

  • release

    • 发布之前merge master

  • dev

    • 通过merge componentX/master整合系统各个部分

    • 此处进行集成测试

  • component1/doc

    • 通过merge doc取得系统总体文档,并添加组件内部设计文档

  • component1/master

    • 在测试稳定后,merge component1/dev

  • component1/dev

    • 在功能开发完毕后,merge component1/featY

  • component1/feat1

    • 在此处开发具体功能

  • component1/feat2

    • 在此处开发具体功能

  • component1/feat3

    • 在此处开发具体功能

  • component2/doc

    • 通过merge doc取得系统总体文档,并添加组件内部设计文档

  • component2/master

    • 在测试稳定后,merge component2/dev

  • component2/dev

    • 在功能开发完毕后,merge component2/featY

  • component2/feat1

    • 在此处开发具体功能

  • component2/feat2

    • 在此处开发具体功能

  • component2/feat3

    • 在此处开发具体功能

  • ...

单repo多分支工作流的具体操作

需要注意的是,不同component分支上的worktree完全不同,互相独立,绝对不能够互相merge,也不能共享同一个worktree; 而同一component里面各个小分支的worktree基本一致,只是有开发先后关系(类似于单体应用的不同分支),适合互相merge,也一般共享同一个worktree。

创建

首先创建repo,不连带创建worktree:

然后给doc和每一个component分别创建一个(小repo和)worktree:

从其他地方clone

不建议使用git clone --bare,因为还需要手工修改fetch信息(参考第5章,这种方式创建的repo默认没有fetch的config项)

建议按上述方法创建,然后再remote add。

doc分支

直接在根目录(the-project/doc)下写文档即可:

component分支

首先配置开发环境(这里以c++为例):

然后从doc分支读取文档:

文档更新以后各component的处理

假设文档在doc更新了:

那么需要在component1分支更新文档:

master

master之于component,就是component之于doc; 唯一区别是一个master会merge多个compoent,而且master上自身代码很少 (可能只有README.md、LICENSE、docker-compose.yml等等全局配置)。

和component完全一致,在master上依次read-tree、write-tree、commit-tree, 就可以将不同组件整合到master上。 别忘了多加几个parent。

FAQ

master要不要直接merge doc

如果在master上进行一些集成测试,那么应该有doc。 否则可以省略。

为什么不用简单方便的git merge -s subtree doc

一些诡异的情况下subtree无法完整地复制doc那边的整个tree的情况, 比如删掉的文件还在、新添加的文件没有出现等等。 参考第6章。

我应该在哪里build

一般来说应该在每个组件各自的worktree里面build, 比如node_modules*.o*.pyc等等。 如果采用docker,那么每个组件分支上应该能生成一个image, 而到了master里面就直接docker-compose up了。

如果出于ci的需要,也可以选择在master里面再次build。但这就需要双倍的磁盘空间。

如何简化操作

参见第8章。另外别忘了git push --allgit log --all等等。

最后更新于

这有帮助吗?