Git版本管理-仓库子模块

486 阅读1分钟

产生背景

在大型项目开发,通用模块希望抽离出来进行独立,并且还能在原本的项目中进行维护或者是独立维护,同时也想保存原本的历史记录。

image.png

Git Submodule 和 Git Subtree

这两个其实都是子模块,Git Submodule允许你将一个Git仓库作为另一个Git仓库的子目录。它能让你将另一个仓库克隆到自己的项目中,同时还保持独立的提交。但是subtree的话,将子模块与父模块融于一体。

image.png

Git Submodule

克隆整个项目

$ git clone --recursive 仓库路径

如果给git clone命令传递--recursive选项,它就会自动初始化并更新仓库中的每一个子模块。

添加子模块

$ git submodule add <仓库地址>  <存放的文件路径>

image.png

结果如下: image.png

更新子模块

$ git fetch && git merge origin/master # 在子模块目录中手动抓取与合并
 
# 或者更简单的方式
$ git submodule update --remote  
# Git将会进入子模块然后抓取并更新,此命令默认更新并检出所有子模块仓库的master分支。
#不过你也可以通过path(相对路径)指定想要更新的子模块、想要更新的分支以及更新后进行的操作。

另一种方式

$ git submodule update --remote --rebase

提交子模块

$ git push --recurse-submodules=on-demand   # 在父项目中运行该命令,会提交所有子模块更新

如果是通过命令直接git clone后,子模块是一个空文件夹,怎么办? 直接按照 .gitmodules 给的路径直接拉取代码,在项目根目录中直接git clone '子模块的路径'

Git Subtree

添加子项目

$ git subtree add --prefix='文件路径' '仓库路径' '分支名' --squash
  1. --prefix:选项指定了子项目对应的子目录
  2. --squash:选项用以压缩Subtree的提交为一个,这样父项目的历史记录里就不会出现子项目完整的历史记录,可加可不加

更新子项目

$ git subtree pull --prefix='文件路径' '仓库路径' '分支名' --squash 

提取子项目

$ git subtree split --prefix='文件路径' --branch '分支名'  # 将'文件路径'这个项目创建为分支'分支名',但没有切换到该分支
$ git branch -a    # 查看所有分支,出现刚创建的分支
$ git checkout '分支名'   # 切换到刚创建的分支
$ git log            # 查看上述过程log信息

--branch指定将生成的历史提交记录保存到一个新的分支。

提交子项目

$ git subtree push --prefix='文件路径' '仓库路径' '分支名'