第23章 子模组协同模型

    项目的版本库在某些情况下需要引用其他版本库中的文件,例如公司积累了一套常用的函数库,被多个项目调用,显然这个函数库的代码不能直接放到某个项目的代码中,而是要独立为一个代码库,那么其他项目要调用公共的函数库该如何处理呢?分别把公共函数库的文件拷贝到各自的项目中会造成冗余,丢弃了公共函数库的维护历史,这显然不是好的方法。本章要讨论的子模组协同模型,就是解决这个问题的一个方案。

    熟悉Subversion的用户马上会想起svn:externals属性可以实现对外部代码库的引用。Git的子模组(submodule)是类似的一种实现。不过因为Git的特殊性,二者的区别还是蛮大的,参见表23-1。

    空标题文档 - 图1

    23.1 创建子模组

    在演示子模组的创建和使用之前,先做些准备工作。先尝试建立两个公共函数库(libA.git和libB.git),以及一个引用函数库的主版本库(super.git)。


    $git—git-dir=/path/to/repos/libA.git init—bare $git—git-dir=/path/to/repos/libB.git init—bare $git—git-dir=/path/to/repos/super.git init—bare

    向两个公共的函数库中填充些数据。这就需要在工作区克隆两个函数库,提交数据并推送。

    克隆libA.git版本库,添加一些数据,然后提交并推送。说明:示例中显示为hack……的地方做了一些改动(如创建新文件等),并将改动添加到暂存区。


    $git clone/path/to/repos/libA.git/path/to/my/workspace/libA $cd/path/to/my/workspace/libA hack… $git commit-m "add data for libA" $git push origin master

    克隆libB.git版本库,添加一些数据,然后提交并推送。


    $git clone/path/to/repos/libB.git/path/to/my/workspace/libB $cd/path/to/my/workspace/libB hack… $git commit-m"add data for libB" $git push origin master

    版本库super是准备在其中创建子模组的。super版本库刚刚初始化还未包含提交,master分支尚未有正确的引用。需要在super版本库中至少创建一个提交。下面就克隆super版本库,在其中完成一个提交(空提交即可),并推送。


    $git clone/path/to/repos/super.git/path/to/my/workspace/super $cd/path/to/my/workspace/super $git commit—allow-empty-m "initialized." $git push origin master

    现在就可以在super版本库中使用git submodule add命令添加子模组了。


    $git submodule add/path/to/repos/libA.git lib/lib_a $git submodule add/path/to/repos/libB.git lib/lib_b

    至此看一下super版本库工作区的目录结构。在根目录下多了一个.gitmodules文件,并且两个函数库分别被克隆到lib/lib_a目录和lib/lib_b目录下。


    $ls-aF ./../.git/.gitmodules lib/

    看看.gitmodules的内容:


    $cat.gitmodules [submodule "lib/lib_a"] path=lib/lib_a url=/path/to/repos/libA.git [submodule "lib/lib_b"] path=lib/lib_b url=/path/to/repos/libB.git

    此时super的工作区尚未提交。


    $git status #On branch master #Changes to be committed: #(use"git reset HEAD<file>…"to unstage) # #new file:.gitmodules #new file:lib/lib_a #new file:lib/lib_b #

    完成提交之后,子模组才算正式在super版本库中创立。运行git push把建立了新模组的本地版本库推送到远程版本库。


    $git commit-m "add modules in lib/lib_a and lib/lib_b." $git push

    在提交过程中,发现作为子模组方式添加的版本库实际上并没有添加版本库的内容。实际上只是以gitlink的方式添加了一个链接。至于子模组的实际地址,是由文件.gitmodules指定的。

    可以通过查看补丁的方式看到lib/lib_a和lib/lib_b子模组的存在方式(即gitlink)。


    $git show HEAD commit 19bb54239dd7c11151e0dcb8b9389e146f055ba9 Author:Jiang Xin<jiangxin@ossxp.com> Date:Fri Oct 29 10:16:59 2010+0800 add modules in lib/lib_a and lib/lib_b. diff—git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..60c7d1f —-/dev/null +++b/.gitmodules @@-0,0+1,6@@ +[submodule "lib/lib_a"] +path=lib/lib_a +url=/path/to/repos/libA.git +[submodule "lib/lib_b"] +path=lib/lib_b +url=/path/to/repos/libB.git diff—git a/lib/lib_a b/lib/lib_a new file mode 160000 index 0000000..126b181 —-/dev/null +++b/lib/lib_a @@-0,0+1@@ +Subproject commit 126b18153583d9bee4562f9af6b9706d2e104016 diff—git a/lib/lib_b b/lib/lib_b new file mode 160000 index 0000000..3b52a71 —-/dev/null +++b/lib/lib_b @@-0,0+1@@ +Subproject commit 3b52a710068edc070e3a386a6efcbdf28bf1bed5