Git submodlue
背景
有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。
我们举一个例子。 假设你正在开发一个网站然后创建了 Atom 订阅。 你决定使用一个库,而不是写自己的 Atom 生成代码。 你可能不得不通过 CPAN 安装或 Ruby gem 来包含共享库中的代码,或者将源代码直接拷贝到自己的项目中。 如果将这个库包含进来,那么无论用何种方式都很难定制它,部署则更加困难,因为你必须确保每一个客户端都包含该库。 如果将代码复制到自己的项目中,那么你做的任何自定义修改都会使合并上游的改动变得困难。
Git 通过子模块来解决这个问题。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。
添加子模块
添加子模块只需要我们在主仓库中执行 git submodule add 子仓库路径
,执行后git会将子仓库中的文件引用到主仓库下。两个仓库就可以在同一个目录下使用了。添加后会生成一个 .gitmodules 文件,里面包含了子模块的相关信息。
[submodule "sub-repo"] path = sub-repo url = git@github.com:name/sub-repo.git
克隆含有子模块的项目
执行git clone的时候默认会包含子模块的目录,但是目录中没有任何文件,需要执行git submodule init
和 git git submodule update
或者合并执行git submodule update --init
,更简单直接的方法是在执行git clone的时候添加参数git clone --recurse-submodules
。
在包含子模块的项目上工作
现在我们有一份包含子模块的项目副本,我们将会同时在主项目和子模块项目上与队员协作。
从子模块的远端拉取上游修改
在项目中使用子模块的最简模型,就是只使用子项目并不时地获取更新,而并不在你的检出中进行任何更改。 我们来看一个简单的例子。如果想要在子模块中查看新工作,可以进入到目录中运行 git fetch
与 git merge
,合并上游分支来更新本地代码。
或者使用更加简单的方式 git submodule update --remote
这条命令会自动帮我们进行抓取合并。默认检测子模块中的master分支,如果需要检测其他的分支则需要在.gitmodules 中进行维护。
$ git config -f .gitmodules submodule.sub-repo.branch 分支名称 $ git submodule update --remote
从项目远端拉取上游更改
从协作者的视角看,当有人在主项目和子模块中进行更改后,协作者本地已经有了main project,这时候只执行git pull拉到的代码只是最新的主仓库的代码,虽然git pull 通过递归可以找到子模块的提交但是需要手动执行 git submodule update --init
获取子模块的更新。