单一仓库或多仓库策略
除了团队规模和节奏,代码结构的方式也会对架构产生影响,如果你想执行逆向Conway法则的话。有两种策略:
-
单一仓库策略(Mono-repo strategy):只有一个仓库,包含应用程序所需的所有模块(或微服务)。
-
多仓库策略(Multi-repo strategy):每个模块或微服务都有自己的仓库,并且你必须部署多个仓库才能让整个应用程序正常工作。
这两种策略都有优缺点。单一仓库策略的最大优势是,部署和调试整个应用程序非常简单。但单一仓库往往会很快变得非常庞大,这会降低Git的性能。而且,随着仓库的增长,独立部署和测试应用程序的不同部分变得更加困难。这导致架构的耦合性更强。
使用大型单一仓库
在Git的上下文中,大仓库指的是包含大量文件和历史记录的仓库,这些仓库的大小会显著影响Git操作的速度和性能。例如,Linux内核的仓库大约有3GB,克隆和使用Git命令的速度虽然较慢,但仍在可接受范围内。然而,Windows仓库大约有300GB,大小是Linux内核的100倍,执行某些Git操作时需要较长时间:
-
git clone:大约需要12小时
-
git checkout:大约需要3小时
-
git status:大约需要8分钟
-
git add 和 git commit:大约需要3分钟
因此,微软维护了自己定制的Git客户端([https://github.com/microsoft/git](https://github.com/microsoft/git))。这个分支包含了许多针对大仓库的优化。它包括了 scalar CLI([https://github.com/microsoft/git/blob/HEAD/contrib/scalar/docs/index.md](https://github.com/microsoft/git/blob/HEAD/contrib/scalar/docs/index.md)),用于设置高级Git配置、在后台维护仓库,并帮助减少网络传输的数据。这些优化极大地减少了在Windows仓库中执行Git操作的时间:
-
git clone:从12小时减少到90秒
-
git checkout:从3小时减少到30秒
-
git status:从8分钟减少到3秒
许多这些优化已经成为标准Git客户端的一部分。例如,你可以使用 git sparse-checkout([https://git-scm.com/docs/git-sparse-checkout](https://git-scm.com/docs/git-sparse-checkout)),允许你只下载仓库中你需要的部分。
如果你的仓库真的非常大,可能需要使用微软的定制版本;否则,通常可以通过正常的Git功能进行优化。
使用主题和星标列表组织您的仓库
多仓库策略的最大优势在于,它减少了单个仓库的复杂性。每个仓库都可以独立维护和部署。最大的劣势是,很难构建和测试整个应用程序。要从真实用户那里获取反馈或调试复杂的错误,通常仅仅部署单个服务或模块是不够的——你需要更新整个应用程序。这意味着需要在你的仓库边界之间协调多个部署。
如果你选择多仓库策略,你将会有许多小仓库。良好的命名约定可以帮助你对它们进行结构化。你还可以使用主题来组织你的仓库。主题可以在仓库的右上角设置(见图17.9)。

你可以使用 topic:
关键词来过滤你的仓库(见图17.10):

另一个可以帮助你组织大量仓库的功能是收藏列表。这是一个个人功能,不能共享。在你的GitHub个人资料中,你可以创建列表并组织你的收藏仓库(见图17.11):

你可以像浏览器中的收藏夹一样使用这些功能,但它们并不能解决部署、调试或测试整个应用程序的问题。
如果你使用的是Kubernetes来管理微服务,你可以在Visual Studio Code中使用Bridge to Kubernetes插件([https://marketplace.visualstudio.com/items?itemName=mindaro.mindaro](https://marketplace.visualstudio.com/items?itemName=mindaro.mindaro))来在生产或测试集群的上下文中调试本地服务(见Medina A. M., 2021)。但是,如果你依赖一次性构建和部署所有服务,最佳的解决方案是拥有一个元仓库,将所有服务作为子模块引用。
使用 Git 子模块结构化您的代码
你可以使用一个元仓库,包含所有其他仓库作为子模块。这使得你可以通过一个命令克隆所有仓库:
$ git clone --recurse-submodules
或者,如果你已经克隆了元仓库,并且想要更新它,可以使用以下命令:
$ git submodule update --init --recursive
该仓库可以包含部署整个应用程序的脚本或工作流。你可以使用这个元仓库进行发布管理,并将稳定的版本捆绑在一起。如果你使用分支来管理发布版本,那么可以将你的子模块设置为某个特定分支,并在发布最新版本之前更新它:
$ git config -f .gitmodules submodule.<SUB>.branch main
$ git submodule update --remote
如果你使用标签来管理发布版本,那么可以将每个子模块设置为特定版本并提交到你的元仓库:
$ cd <SUB>
$ git checkout <TAG>
$ cd ..
$ git add <SUB>
$ git commit -m "Update <SUB> to <TAG>"
$ git push
其他人可以拉取更改并更新子模块到与标签相对应的版本:
$ git pull
$ git submodule update --init --recursive
Git子模块是处理多仓库并独立部署的一个很好的方式,同时仍然能够将整个应用程序进行管理。但是请注意,你的子模块之间的依赖关系越多,维护元仓库并保持它们处于可部署状态的复杂度就越高。