通过子模块和子树来管理 Git 项目

如果你参与了开源项目的开发,那么你很可能已经用了 Git 来管理你的源码。你可能遇到过有很多依赖和/或子项目的项目。你是如何管理它们的?对于一个开源组织,要实现社区和产品的单一来源文档和依赖管理比较棘手。文档和项目往往会碎片化和变得冗余,这致使它们很难维护。

必要性

假设你想把单个项目作为一个存储库内的子项目,传统的方法是把该项目复制到父存储库中,但是,如果你想要在多个父项目中使用同一个子项目呢?如果把子项目复制到所有父项目中,当有更新时,你都要在每个父项目中做修改,这是不太可行的。这会导致父项目中的冗余和数据不一致,使更新和维护子项目变得很困难。

Git 子模块和子树

如果你可以用一条命令把一个项目放进另一个项目中,会怎样呢?如果你随时可以把一个项目作为子项目添加到任意数目的项目中,并可以同步更新修改呢?Git 提供了这类问题的解决方案:Git 子模块submodule和 Git 子树subtree。创建这些工具的目的是以更加模块化的水平来支持共用代码的开发工作流,旨在 Git 存储库源码管理source-code management(SCM)与它下面的子树之间架起一座桥梁。

下面是本文要详细介绍的概念的一个真实应用场景。如果你已经很熟悉树形结构,这个模型看起来是下面这样:

Git 子模块是什么?

Git 在它默认的包中提供了子模块,子模块可以把 Git 存储库嵌入到其他存储库中。确切地说,Git 子模块指向子树中的某次提交。下面是我 Docs-test GitHub 存储库中的 Git 子模块的样子:

如何使用子模块和子树来管理 Git 项目如何使用子模块和子树来管理 Git 项目

文件夹@提交 Id 格式表明这个存储库是一个子模块,你可以直接点击文件夹进入该子树。名为 .gitmodules 的配置文件包含所有子模块存储库的详细信息。我的存储库的 .gitmodules 文件如下:

如何使用子模块和子树来管理 Git 项目如何使用子模块和子树来管理 Git 项目

你可以用下面的命令在你的存储库中使用 Git 子模块:

克隆一个存储库并加载子模块

克隆一个含有子模块的存储库:

$ git clone --recursive

如果你之前已经克隆了存储库,现在想加载它的子模块:

$ git submodule update --init

如果有嵌套的子模块:

$ git submodule update --init --recursive

下载子模块

串行地连续下载多个子模块是很枯燥的工作,所以 clone 和 submodule update 会支持 –jobs (或 -j)参数:

例如,想一次下载 8 个子模块,使用:

$ git submodule update --init --recursive -j 8
$ git clone --recursive --jobs 8

拉取子模块

在运行或构建父项目之前,你需要确保依赖的子项目都是最新的。

拉取子模块的所有修改:

$ git submodule update --remote

使用子模块创建存储库: 向一个父存储库添加子树:

$ git submodule add

初始化一个已存在的 Git 子模块:

$ git submodule init

你也可以通过为 submodule update 命令添加 –update 参数在子模块中创建分支和追踪提交:

$ git submodule update --remote

更新子模块的提交

上面提到过,一个子模块就是一个指向子树中某次提交的链接。如果你想更新子模块的提交,不要担心。你不需要显式地指定最新的提交。你只需要使用通用的 submodule update 命令

$ git submodule update

就像你平时创建父存储库和把父存储库推送到 GitHub 那样添加和提交就可以了。

从一个父存储库中删除一个子模块

仅仅手动删除一个子项目文件夹不会从父项目中移除这个子项目。想要删除名为 childmodule 的子模块,使用:

$ git rm -f childmodule

虽然 Git 子模块看起来很容易上手,但是对于初学者来说,有一定的使用门槛。

Git 子树是什么?

Git 子树,是在 Git 1.7.11 引入的,让你可以把任何存储库的副本作为子目录嵌入另一个存储库中。它是 Git 项目可以注入和管理项目依赖的几种方法之一。它在常规的提交中保存了外部依赖信息。Git 子树提供了整洁的集成点,因此很容易复原它们。

如果你参考 GitHub 提供的子树教程来使用子树,那么无论你什么时候添加子树,在本地都不会看到 .gittrees 配置文件。这让我们很难分辨哪个是子树,因为它们看起来很像普通的文件夹,但是它们却是子树的副本。默认的 Git 包中不提供带 .gittrees 配置文件的 Git 子树版本,因此如果你想要带 .gittrees 配置文件的 git-subtree 命令,必须从 Git 源码存储库的 /contrib/subtree 文件夹 下载 git-subtree。

你可以像克隆其他常规的存储库那样克隆任何含有子树的存储库,但由于在父存储库中有整个子树的副本,因此克隆过程可能会持续很长时间。

你可以用下面的命令在你的存储库中使用 Git 子树。

向父存储库中添加一个子树

想要向父存储库中添加一个子树,首先你需要执行 remote add,之后执行 subtree add 命令:

$ git remote add remote-name
$ git subtree add --prefix=folder/ remote-name  subtree-branchnam

上面的命令会把整个子项目的提交历史合并到父存储库。

向子树推送修改以及从子树拉取修改

$ git subtree push-all

或者

$ git subtree pull-all

你应该使用哪个?

任何工具都有优缺点。下面是一些可能会帮助你决定哪种最适合你的特性:

Git 子模块的存储库占用空间更小,因为它们只是指向子项目的某次提交的链接,而 Git 子树保存了整个子项目及其提交历史。

Git 子模块需要在服务器中可访问,但子树是去中心化的。

Git 子模块大量用于基于组件的开发,而 Git 子树多用于基于系统的开发。

Git 子树并不是 Git 子模块的直接可替代项。有明确的说明来指导我们该使用哪种。如果有一个归属于你的外部存储库,使用场景是向它回推代码,那么就使用 Git 子模块,因为推送代码更容易。如果你有第三方代码,且不会向它推送代码,那么使用 Git 子树,因为拉取代码更容易。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/221451.html<

赞 (0)
管理的头像管理
上一篇2025-04-15 01:09
下一篇 2025-04-15 01:10

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注