Git Submodule和Git Subtree使用

1. 前言

Git Submodule和Git Subtree都是Git版本控制系统中用于管理代码库中的子项目的功能。

  1. Git Submodule(子模块):

    • 子模块是指将一个独立的Git仓库作为另一个Git仓库的一部分引入。
    • 子模块允许在一个代码库中包含另一个代码库,并将其视为子模块的一部分,可以在父仓库和子仓库之间进行独立的版本控制。
    • 子模块通过在父仓库中保存子仓库的引用,并将其作为一个单独的目录存在。
    • 子模块的更新需要手动执行特定的命令。
  2. Git Subtree(子树):

    • 子树允许将一个Git仓库的子目录复制到另一个Git仓库中,并保持两者独立的版本历史。
    • 子树是通过复制子仓库的指定目录,并将其作为父仓库的子目录来实现的。
    • 子树可以用于将一个项目的代码以及相关的提交历史集成到另一个项目中,而不需要将整个子仓库作为子模块引入。
    • 子树的更新可以像其他Git提交一样进行,不需要特殊的命令。

两者的选择取决于具体的使用场景和需求:

  • 如果您希望在父仓库和子仓库之间保持独立的版本控制,并且需要手动管理子仓库的更新(如切换分支、拉取最新代码等),那么可以选择Git Submodule。
  • 如果您只是希望将一个项目的部分代码集成到另一个项目中,并且希望能够像处理普通代码一样管理子目录的更新,那么可以选择Git Subtree。

2. submodule 使用

2.1 初始化项目

主项目main-git: git clone [email protected]:f5l5y5/main-git.git

子项目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 目录下

扫描二维码关注公众号,回复: 15595909 查看本文章

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,你会选择哪个来管理子项目?

猜你喜欢

转载自juejin.im/post/7253391363453288506