Git Submodule and Git Subtree use

1 Introduction

Both Git Submodule and Git Subtree are functions in the Git version control system for managing subprojects in a code repository.

  1. Git Submodule (submodule):

    • Submodules refer to bringing in an independent Git repository as part of another Git repository.
    • Submodules allow one codebase to be included in another codebase and treated as part of the submodule, enabling independent version control between the parent and child repositories.
    • Submodules work by keeping a reference to the subrepo in the parent repository as a separate directory.
    • Submodule updates require specific commands to be executed manually.
  2. Git Subtree (subtree):

    • Subtrees allow copying subdirectories of one Git repository into another Git repository, keeping separate version histories for both.
    • Subtrees are implemented by duplicating the specified directory of the subrepo and making it a subdirectory of the parent repo.
    • Subtrees can be used to integrate code from one project, along with the associated commit history, into another without requiring the entire subrepo to be brought in as a submodule.
    • Subtree updates can be made like any other Git commit, no special commands are required.

The choice of the two depends on the specific usage scenarios and requirements:

  • If you want to maintain independent version control between the parent warehouse and the sub-warehouse, and need to manually manage the updates of the sub-warehouse (such as switching branches, pulling the latest code, etc.), you can choose Git Submodule.
  • If you just want to integrate part of the code of one project into another project, and want to be able to manage the update of subdirectories like normal code, you can choose Git Subtree.

2. Submodule use

2.1 Initialize the project

Main project main-git: git clone [email protected] :f5l5y5/main-git.git

Sub-project sub-components: git clone [email protected] :f5l5y5/sub-components.git

子项目:sub-utils: git clone [email protected]:f5l5y5/sub-utils.git

添加子模块:

git submodule add [email protected]:f5l5y5/sub-utils.git utils

git submodule add [email protected]:f5l5y5/sub-components.git components

命令说明: 添加子模块到当前文件夹下 utils/components 目录下

2. 提交、拉取、更新

  1. 提交

修改子项目sub-utils,需要进入utils文件夹,进行单独提交。此时父项目会有一条关于子项目变更记录,进行提交即可。 单独拥有自己的.git文件,commit也是单独的。

例如:

修改子项目:

image.png

父项目:

image.png

两个进行提交后:

image.png

image.png

  1. 拉取、更新

拉取仓库主项目代码:git clone [email protected]:f5l5y5/main-git.git子项目没有文件

image.png

获取子项目代码:

git submodule init
git submodule update
// 合并
git submodule update --init

image.png

嵌套子项目情况:

git submodule update --init --recursive // 递归进行更新拉取

image.png

  1. 一次性拉取

git clone --recursive git@github.com:f5l5y5/main-git.git
或
git clone --recurse-submodules git@github.com:f5l5y5/main-git.git

image.png

总结

  1. 添加子模块:

    git submodule add <子模块仓库URL> <子模块目录>
    

    这个命令将子模块添加到父仓库中,并指定子模块的仓库URL和子模块在父仓库中的目录位置。

  2. 克隆父仓库和子模块:

    • 如果你是第一次克隆父仓库,可以使用以下命令:
      git clone --recurse-submodules <父仓库的URL>
      
      这个命令会同时克隆父仓库和子模块,并获取子模块的代码和提交历史。
    • 如果你已经克隆了父仓库但没有子模块的代码,请在父仓库的根目录中执行以下命令:
      git submodule update --init --recursive
      
  3. 更新子模块:

    • 进入父仓库的根目录,在命令行中执行以下命令来更新子模块:
      git submodule update --remote <子模块目录>
      
      这个命令将拉取子模块的最新代码。
  4. 切换子模块分支:

    • 进入父仓库的根目录,在命令行中执行以下命令来切换子模块的分支:
      cd <子模块目录>
      git checkout <分支名>
      git pull origin <分支名>
      cd ..
      
      这个命令将在子模块中切换到指定分支,并拉取最新代码。

3. subtree使用

3.1 添加子树

git subtree add --prefix=components git@github.com:f5l5y5/sub-components.git main

git subtree add --prefix=utils git@github.com:f5l5y5/sub-utils.git main

必须在顶层运行: image.png

运行后:

  1. 子项目没有.git 文件
  2. subtree 的方式在创建目录的时候会生成一个 commit

文件结构: image.png

3.2 提交、拉取、更新

  1. 提交

如果修改子项目一个文件

git add .
git commit -m "xxx"
git push origin main //推送主项目 

如果在主项目中直接使用git push 子项目是不会更新

只推送子项目

git remote add utils git@github.com:f5l5y5/sub-utils.git // 定义utils远程仓库别名

git subtree push --prefix=utils utils main
  1. 拉取、更新
  • 直接拉取,会将所有子项目拉取
  • 更新,如果子项目有更新,主项目需要更新,则使用git subtree pull --prefix=utils gitUrl main

更新是会生成一条merge记录,将子项目的提交合并到主项目。

image.png

subtree使用总结

以下是Git Subtree的一些常用操作和用法:

  1. 添加子树:

    • 添加一个子树到父仓库:
      git subtree add --prefix=<子树目录> <子树仓库URL> <子树分支>
      
  2. 拉取子树更改:

    • 提取子树的更改到父仓库中:
      git subtree pull --prefix=<子树目录> <子树仓库URL> <子树分支>
      
  3. 推送子树更改:

    • 推送父仓库对子树的更改到子树仓库:
      git subtree push --prefix=<子树目录> <子树仓库URL> <子树分支>
      
    • 示例:
  4. 查看子树的提交历史:

    • 查看子树的提交历史:
      git log --prefix=<子树目录>
      
    • 示例:
      git log --prefix=vendor/mylibrary
      
  5. 移除子树:

    • 从父仓库中移除子树:
      git subtree remove --prefix=<子树目录>
      

总结

git submodule和subtree根据使用场景自己进行选择,主要区别如下:

总结 submodule subtree
添加 git submodule add gitUrl 文件夹名称 git subtree add --prefix=文件夹名称 gitUrl branch
.git文件 每个子项目都会有单独的.git 子项目没有单独的.git
单独提交子代码 到子项目文件夹下 使用git subtree push --prefix=utils gitUrl main
主项目提交代码 子项目提交主项目会生成记录 可以直接提交,不会影响子项目
拉取子项目更新 git submodule update --recursive git subtree pull --prefix=utils gitUrl main --squash

参考文章:

git submodule 和 git subtree,你会选择哪个来管理子项目?

Guess you like

Origin juejin.im/post/7253391363453288506