「译文」使用 submodule 和 subtree 管理 Git 项目

本文最后更新于:2022年4月27日 下午

👉️URL: https://opensource.com/article/20/5/git-submodules-subtrees

✍️ Author: Manaswini Das (Red Hat)

📝Description:

submodule 和 subtree 帮助您管理跨多个存储库的子项目。

如果你从事开源开发,你可能已经用 Git 来管理源代码了。你可能遇到过有许多依赖关系和 / 或子项目的项目。你如何管理它们呢?

对于一个开源组织来说,为社区和产品实现单一来源的文档和依赖性管理可能是很棘手的。文档和项目最终往往是零散的和多余的,这使得它们难以维护。

需求

假设你想在一个版本库中使用一个单一的项目作为子项目。传统的方法只是把项目复制到父版本库中。但是,如果你想在许多父版本库中使用同一个子项目呢?如果把子项目复制到每个父库中,并且每次更新都要在所有的父库中进行修改,那是不可行的。这将在父项目库中产生冗余和不一致,并使更新和维护子项目变得困难。

Git submodules 和 subtrees

如果你可以用一个命令把一个项目放在另一个项目中,会怎么样?如果你可以把项目作为子项目添加到任何数量的项目中,并随时随地推送更改,那会怎么样?Git 提供了这方面的解决方案。Git 子模块和 Git 子树。这些工具的创建是为了在更多的模块化层面上支持代码共享开发工作流程,希望能在 Git 仓库的源代码管理(SCM)和其中的子库之间架起一座桥梁。

这是本文将详细介绍的概念的一个现实生活场景。如果你已经熟悉了树,这里就是这个模型的样子。

Tree with subtrees

Image by:

CC BY-SA opensource.com

什么是 Git submodules?

Git 在其默认包中提供了 submodule,使 Git 仓库可以嵌套在其他仓库中。准确地说,Git submodule 指向子仓库的一个特定提交。下面是我的 Docs-test GitHub repo 中的 Git 子模块的样子。

包含 submodule 的 git 仓库截图

folder@commitId的格式表示该版本库是一个子模块,你可以直接点击该文件夹进入子版本库。名为 .gitmodules 的配置文件包含所有子模块仓库的细节。我的 repo 的 .gitmodules 文件看起来像这样。

.gitmodules 截图

你可以使用以下命令在你的仓库中使用 Git 子模块。

克隆一个版本库并加载 submodule

要克隆一个包含 submodule 的版本库。

1
git clone --recursive <URL to Git repo>

如果你已经克隆了一个版本库,并想加载其子模块。

1
git submodule update --init

如果有嵌套的子模块。

1
git submodule update --init --recursive

下载 submodules

按顺序下载子模块可能是一项繁琐的工作,所以 克隆 子模块更新 支持 **–job-j** 参数。

例如,要一次下载 8 个子模块,请使用。

1
2
git submodule update --init --recursive -j 8
git clone --recursive --jobs 8 <URL to Git repo>

Pull submodules

在运行或构建父版本库之前,你必须确保子版本库的依赖关系是最新的。

要拉动子模块中的所有修改。

1
git submodule update --remote

用子模块创建存储库

要添加一个子库到父库。

1
git submodule add <URL to Git repo>

要初始化一个现有的 Git 子模块。

1
git submodule init

你也可以通过在你的 submodule update 命令中添加 **–update** 来创建分支和跟踪提交。

1
git submodule update --remote

升级 submodule commits

如上所述,子模块是一个链接,指向子版本库中的一个特定提交。如果你想更新子模块的提交,不必担心。你不需要明确指定最新的提交。你可以直接使用一般的 submodule update 命令。

1
git submodule update

只要像平时那样添加和提交,就可以创建并推送父仓库到 GitHub。

从父版本库中删除一个子模块

仅仅手动删除一个子项目文件夹并不能从父版本库中删除该子项目。要删除一个名为 childmodule 的子模块,请使用。

1
git rm -f childmodule

尽管 Git submodule 看起来很容易操作,但对于初学者来说,要找到它们的方法可能很困难。

什么是 Git subtrees?

Git subtree,在 Git 1.7.11 中引入,允许你插入任何仓库的副本作为另一个仓库的子目录。它是 Git 项目注入和管理项目依赖关系的几种方式之一。它将外部依赖关系存储在常规提交中。Git subtree 提供了干净的集成点,所以它们更容易被恢复。

如果你使用 GitHub 提供的 subtrees 教程 来使用 subtrees,那么每当你添加一个 subtrees 时,你不会在本地看到一个 **.gittrees 配置文件。这使得人们很难识别子树,因为子树看起来像一般的文件夹,但它们是子仓库的副本。带有 .gittrees 配置文件的 Git 子树版本在默认的 Git 软件包中是没有的,所以要获得带有.gittrees** 配置文件的 git-subtree,你必须从 Git 源仓库的 **/contrib/subtree ** 文件夹 中下载 git-subtree。

你可以克隆任何包含 subtree 的仓库,就像其他一般仓库一样,但可能需要更多时间,因为子仓库的整个副本都在父仓库中。

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

为父库添加 subtree

要向父版本库添加一个新的子树,首先需要 remote add,然后运行subtree 添加命令,比如。

1
2
git remote add remote-name <URL to Git repo>
git subtree add --prefix=folder/ remote-name <URL to Git repo> subtree-branchname

这将整个子项目的提交历史合并到父版本库中。

向 subtree push 和 pull changes

1
git subtree push-all

1
git subtree pull-all

你应该使用哪种方法?

每个工具都有优点和缺点。这里有一些特点,可以帮助你决定哪种工具最适合你的使用情况。

  • Git submodule 的仓库大小较小,因为它们只是指向子项目中特定提交的链接,而 Git subtree 则容纳整个子项目及其历史。
  • Git submodule 需要在服务器中可访问,但子树是分散的。
  • Git submodule 主要用于组件开发,而 Git subtree 主要用于系统开发。

Git subtree 并不是 Git submodule 的直接替代品。有一些注意事项可以指导两者的使用。如果有一个你自己的外部仓库,并且有可能推送代码回去,使用 Git submodule,因为它更容易推送。如果你有不太可能推送的第三方代码,使用 Git subtree,因为它更容易拉取。

试一试 Git 子树和子模块,并在评论中告诉我情况如何。

Creative Commons License 本作品采用知识共享署名 - 相同方式共享 4.0 国际许可协议进行许可。


「译文」使用 submodule 和 subtree 管理 Git 项目
https://ewhisper.cn/posts/34308/
作者
东风微鸣
发布于
2022年4月27日
许可协议