Submodules

为什么有 Submodules

在复杂的项目中,常常会引用一些公共基础库或将代码拆分为公共模块和多个子模块进行管理。在主项目工程中,子模块需要依赖于公共模块,但并不需要关心公共模块内部的开发流程细节。直接将公共代码复制到项目中不合适,因为这样会导致更新和维护困难。为了解决这个问题,有一些成熟的实践方法,其中常见的是使用 npm 和 git submodule 两种方式。

然而,针对频繁增加业务逻辑并需要频繁发布和更新 package 的情况,npm 这个方案不够合适。因此,可以考虑使用 git submodule 实现公共模块的管理。使用 git submodule 可以将公共模块作为子模块添加到主项目中,子模块可以独立地更新和维护。这种方式能够方便地保持子模块与公共模块的依赖关系,并且能够灵活地管理和集成公共模块的更新。

综上所述,对于复杂项目中的公共模块管理问题,使用 git submodule 的方式可以提高代码的可维护性和可更新性,减少重复代码,灵活管理公共模块的依赖关系,适应频繁的业务逻辑增加和发布更新需求。

了解 Git Submodules

Git Submodules 是 Git 版本控制系统提供的一个功能,用于在一个 Git 仓库中添加另一个 Git 仓库作为子模块。子模块允许您将一个独立的代码库嵌入在主项目中,并在主项目中跟踪子模块的版本、历史记录和更改。

虽然 git submodule 需要一定的学习成本,但也有其不可取代的优势:

  • 代码复用和共享:使用Git Submodules可以将一个独立的代码库嵌入到多个项目中,实现代码的复用和共享,避免重复编写和维护相同的代码。

  • 模块化开发:通过将项目拆分为多个子模块,每个子模块都有独立的仓库和开发流程,可以实现模块化开发和维护,提高代码的可维护性和可扩展性。

  • 独立更新和版本控制:每个子模块都有自己的版本控制,可以独立地更新和维护。子模块的更新和提交不会影响到主项目和其他子模块,保持了代码的独立性和可控性。

  • 分布式团队协作:Git Submodules适用于分布式团队协作,团队成员可以独立地开发和维护子模块,不同团队成员可以并行开发不同的模块,以提高协作效率。

创建 submodule

按照以下步骤操作创建一个Git Submodule:

  1. 使用以下命令将子模块添加到主项目中:

    $ git submodule add <repository_url> <submodule_path>
    

    其中,<repository_url> 是子模块的远程仓库地址,<submodule_path> 是子模块在主项目中的路径。

    此时,项目中会多出两个文件:.gitmodules 和子模块项目文件夹,以及在 .git/config 文件和 .git/modules 文件夹下也会多出相关内容。在此期间,git 做了3件事情:

    • 记录引用的仓库
    • 记录主项目中 submodules 的目录位置
    • 记录引用 submodule 的 commit id
  2. 执行上述命令后,Git会自动将子模块的仓库克隆到 <submodule_path> 目录下。完成后,会显示一条消息确认子模块的添加。

  3. 使用以下命令可以查看现有的子模块清单:

    $ git submodule status
    
  4. 如果需要将主项目中的修改提交到子模块,首先需要在子模块的目录中执行提交操作,然后在主项目的目录中执行提交操作。提交后,在主项目仓库中,会显示出子模块文件夹,并附带其所在仓库的版本号,如:foo @ abcd1234。这样可以保持主项目和子模块的提交记录独立。

这样,就成功地添加了一个Git Submodule到主项目中。子模块的更新和维护可以在子模块的仓库中进行,主项目只需引用和跟踪子模块的版本即可。

Submodules 的父子关系存在哪里

子模块与父项目之间的关系存在于父项目的版本控制中,通过 .gitmodule 文件和 .git/config 文件记录子模块的地址、路径和配置信息。父项目追踪子模块的特定版本或提交,并通过父项目的版本控制来更新子模块的引用。子模块本身具有独立的版本控制和仓库,可以独立地开发、维护和更新。这种父子关系的管理方式保证了子模块与父项目在版本上的一致性。

Submodules 的父子关系信息怎么存

父子关系信息存储在两个文件中:

  1. .gitmodules 文件:记录了子模块的路径、URL等信息。
    [submodule "submodule_path"]
        path = submodule_path
        url = https://github.com/example/submodule.git
    
  2. .git/config 文件:记录了父项目的配置信息,包括子模块的引用和相关设置。
    [submodule "submodule_path"]
        url = https://github.com/example/submodule.git
        branch = master
    

这些文件中的信息告知 Git 如何管理和跟踪子模块。父项目通过这些文件存储父子关系信息,并跟踪子模块的特定版本或提交。子模块本身具有独立的版本控制和仓库,父项目只是记录和管理子模块的引用。

获取 Submodules

要获取子模块,需要执行以下步骤:

  1. 克隆父项目:首先,使用Git命令或图形化工具克隆父项目的仓库。

  2. 初始化子模块:进入父项目的根目录,在终端或命令行中执行以下命令,初始化子模块:

    $ git submodule init
    
  3. 更新子模块:执行以下命令,以获取子模块的最新代码:

    $ git submodule update
    

    如果子模块有多个分支,可以使用以下命令切换到特定分支:

    $ git submodule update --remote --checkout
    

    这将更新子模块并检出父项目所使用的特定分支。

在执行完以上步骤后,你将成功获取子模块。子模块的代码会存储在父项目目录中的子目录中,可以在父项目中使用子模块的功能。需要注意的是,子模块本身具有独立的仓库和版本控制,你可以在子模块目录中进行独立的开发和更新。

也可以在 clone 命令中添加 --recurse-submodules 或 --recursive 参数递归拉取子模块代码

$ git clone --recurse-submodules <repository_url>

执行$ git clone --recursive http://10.100.10.51/Bonobo.Git.Server/Module.git报以下错误:
git help 解释:--recursive, --recurse-submodulesAfter the clone is created, initialize all submodules within, using their default settings. This is equivalent to running gitsubmodule update --init --recursive immediately after the clone is finished. This option is ignored if the cloned repositorydoes not have a worktree/checkout (i.e. if any of --no-checkout/-n, --bare, or --mirror is given)

对于git 2.13及更高版本,可以使用--recurse-submodules代替--recursive

更新子模块

当子模块有更新时,在主仓库需要更新一下远程子模块代码

$ git submodule update --remote

查看当前子模块

$ git submodule status

删除子模块

要删除子模块,可以按照以下步骤进行操作:

  1. 删除子模块的引用:在终端或命令行中,进入到父项目的根目录,执行以下命令删除子模块的引用:

    $ git submodule deinit <子模块路径>
    

    例如,如果子模块位于路径 submodule_path,则命令应为:

    $ git submodule deinit submodule_path
    

    使用 git submodule deinit 命令卸载一个子模块。这个命令如果添加上参数 --force,则子模块工作区内即使有本地的修改,也会被移除。

     $ git submodule deinit <子模块路径>
     $ git rm <子模块路径>
    

    执行git submodule deinit 命令的实际效果,是自动在 .git/config 中删除了以下内容

    error: the following file has changes staged in the index:
    Front-End/submodule
    (use --cached to keep the file, or -f to force removal)
    fatal: Submodule work tree 'Front-End/submodule' contains local modifications; use '-f' to discard them

    解决:git rm --cached Front-End/submodule

    [submodule "Front-End/submodule"]
            url = http://10.100.10.51/Bonobo.Git.Server/Module.git
            active = true
    
  2. 删除子模块的目录:执行以下命令删除子模块的目录:

    $ git rm -rf <子模块路径>
    

    例如,如果子模块位于路径 submodule_path,则命令应为:

    $ git rm -rf submodule_path
    

    最后执行:

    $ git rm --cached 
    
  3. 更新父项目的版本控制:执行以下命令提交父项目的版本控制变更:

    $ git commit -m "Remove submodule"
    
  4. 删除子模块的记录:编辑父项目的.gitmodules文件,删除包含子模块信息的相应行。

    [submodule "submodule_path"]
        path = submodule_path
        url = https://github.com/example/submodule.git
    

    将其从.gitmodules文件中删除。

  5. 更新父项目的版本控制(再次):执行以下命令提交对.gitmodules文件的变更:

    $ git commit -m "Remove submodule reference"
    

完成以上步骤后,子模块将被从父项目中删除。请注意,这只是移除了子模块的引用和记录,并没有删除子模块本身的仓库。如果您不再需要子模块,并且希望完全删除它,您需要手动删除子模块的仓库文件。

posted @ 2023-08-11 11:58  孤持的庄稼人  阅读(116)  评论(0编辑  收藏  举报