产生背景
在大型项目开发,通用模块希望抽离出来进行独立,并且还能在原本的项目中进行维护或者是独立维护,同时也想保存原本的历史记录。
Git Submodule 和 Git Subtree
这两个其实都是子模块,Git Submodule允许你将一个Git仓库作为另一个Git仓库的子目录。它能让你将另一个仓库克隆到自己的项目中,同时还保持独立的提交。但是subtree的话,将子模块与父模块融于一体。
Git Submodule
克隆整个项目
$ git clone --recursive 仓库路径
如果给git clone命令传递--recursive选项,它就会自动初始化并更新仓库中的每一个子模块。
添加子模块
$ git submodule add <仓库地址> <存放的文件路径>
结果如下:
更新子模块
$ 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
- --prefix:选项指定了子项目对应的子目录
- --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='文件路径' '仓库路径' '分支名'