转自
Title: 管理带有子模块的git库(以 DragonBonesCPP 为例)
Date: 2014-04-19 15:48:25 Modified: 2015-09-06 17:59:20 Author: zrong Postid: 2096 Slug: 2096 Nicename: manage_a_git_library_with_submodules Category: technology Tags: cpp, dragonbones, git, skeletalanimation Attachments: 2097, 20982015-09-06 更新: 加入 的内容。
是一个包含子模块的库,在 clone/commit/push 的时候需要一些额外的操作。
本文将描述这些操作。
子模块(submodule)
限(wei)于(le)篇(tou)幅(lan),请自行学习下面的内容:
clone DragonBonesCPP
蛋碎方法一
git clone --recursive git@github.com:DragonBones/DragonBonesCPP.git
使用这个方法,将会自动 clone 该项目下的所有子模块。这其实是最简单的方法了。
为什么说它令人蛋碎呢?因为 DragoneBones 中包含的 engines/cocos2d-x 子模块也包含子模块。
这样就出现了嵌套子模块,一个 cocos2d-x 的所有历史加起来就超过1G了,再加上子模块的所有历史,这就……。
蛋疼方法二
为了避免蛋碎的问题,我们换一个方法,可是蛋疼是免不了了。
# git clone git@github.com:DragonBones/DragonBonesCPP.gitCloning into 'DragonBonesCPP'...remote: Counting objects: 103, done.remote: Compressing objects: 100% (87/87), done.remote: Total 103 (delta 18), reused 96 (delta 13)Receiving objects: 100% (103/103), 88.96 KiB | 47 KiB/s, done.Resolving deltas: 100% (18/18), done.
此时已经将所有 DragonBonesCPP 的核心代码 clone 下来了,由于项目不大,这个过程会非常快。
但是子模块不会自动 clone,接下来需要设置子模块。
# cd DragonBonesCPP# DragonBonesCPP git:(master) > git submodule status-a7709c35badbd930f98adaf1c172a3251f8c6543 engines/cocos2d-x
refid 前面的减号 - 代表子模块还没有加载,我们需要初始化并检出它:
# DragonBonesCPP git:(master) > git submodule initSubmodule 'cocos2d-x' (git@github.com:DragonBones/cocos2d-x.git) registered for path 'engines/cocos2d-x'# DragonBonesCPP git:(master) > git submodule updateCloning into 'engines/cocos2d-x'...remote: Reusing existing pack: 200502, done.Receiving objects: 100% (200502/200502), 763.78 MiB | 98 KiB/s, done.Resolving deltas: 100% (133006/133006), done.Submodule path 'engines/cocos2d-x': checked out 'a7709c35badbd930f98adaf1c172a32 51f8c6543'
等待是漫长的,看我的网速就知道这到底花了多长时间。
和蛋碎方法不同的是,这种方法不会 clone cocos2d-x 中的子模块(嵌套子模块)。若有需要,可以进入 cocos2d-x 中再次执行蛋疼方法二。
分支
DragonBonesCPP 的分支介绍
DragonBonesCPP 项目目前有2个分支, 和 ,区别如下:
- 分支中包含的内容是稳定的或者基于稳定版本的引擎。
- 分支中包含的内容是目前正在开发的功能或者基于开发版本的引擎。
以对 引擎的支持为例:
- 分支包含对 cocos2d-x 2.x 版本的支持;
- 分支包含对 cocos2d-x 3.x 版本的支持。
切换分支
在开发的过程中,我们经常需要切换分支。例如对 cocos2d-x 2.x 的相关功能进行修改后(位于master分支),希望切换到 cocos2d-x 3.x 的另一些功能进行修改。
这种情况下,我们一般使用 git checkout 来切换分支。于是,奇怪的事情发生了:
# DragonBonesCPP git:(master) > git checkout devM engines/cocos2d-xSwitched to branch 'dev'# DragonBonesCPP git:(dev) > git status On branch dev Changes not staged for commit: (use "git add..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: engines/cocos2d-x (new commits)no changes added to commit (use "git add" and/or "git commit -a")
显然我们切换分支后还没有对dev进行修改,但dev分支中已经出现了一个 modified!
diff 看看有什么不同:
DragonBonesCPP git:(dev) > git diffdiff --git a/engines/cocos2d-x b/engines/cocos2d-xindex 123b410..a7709c3 160000--- a/engines/cocos2d-x+++ b/engines/cocos2d-x@@ -1 +1 @@-Subproject commit 123b410b99510e4a33ceadc08abc09d292f5df49+Subproject commit a7709c35badbd930f98adaf1c172a3251f8c6543
从比较的结果看来,子模块指向的 refid 发生了变化,从 123b410... 变成了 a7709c3... 。
wwwwait! 这两个id怎么看着那么眼熟捏?原来,他们分别是 master 和 dev 分支中的 cocos2d-x 子模块指向的 refid。见下图:
也就是说,虽然从 master 切换到了 dev 分支,但是子模块 cocos2d-x 中 HEAD 指向的 refid 并没有跟着改变到 dev 分支中应有的指向。
为了进一步证明这个推测,我们可以进入子模块 cocos2d-x 中查看所处分支: (注意下面的操作位于子模块 cocos2d-x 中)
# DragonBonesCPP git:(dev) > cd engines/cocos2d-x# cocos2d-x git:(master) > git status# On branch masternothing to commit, working directory clean
注意,在这里可以看到,我们并不是位于我们期望的 cocos2d-x 的 develop 分支(这是 cocos2d-x 3.x的所在分支),而是依然位于 master(cocos2d-x 2.x的所在分支) 分支。
知道了原因,切换起来就简单了。我们只需要进入 cocos2d-x 子模块,将现有的指向改为 cocos2d-x 的 develop 分支即可。
# cocos2d-x git:(master) > git checkout developSwitched to branch 'develop'# cocos2d-x git:(develop) cd ../../# DragonBonesCPP git:(dev) git status# On branch dev# Your branch is ahead of 'origin/dev' by 3 commits.# (use "git push" to publish your local commits)#nothing to commit, working directory clean
看吧,没有提交,世界清静了。
合并分支
由于我们使用了分支来区分不同的版本,因此在合并的时候,必须做一些处理确保正常。
例如,对于 renderer 中的内容,一定是基于分支独立的。它们不应该在合并的时候被处理。
- master 分支中的 renderer ,与 dev 分支中的 renderer 就可能完全不同,我们不希望在将 master 分支合并到 dev 分支(或者相反)的时候,导致完全不同的两个渲染器互相冲突;
- 而 library 中的内容,则恰恰相反,它们需要在分支之间合并。
文件可以解决这个问题,可参阅这里: 。
为了解决这个矛盾,我已在 .gitattributes 中将 renderer 和 engines 目录排除,在合并的时候,它们将保存各自的版本。
若有更深入的需求,例如 renderer 中的某些渲染器需要合并而有些不要,则后续进一步处理。
提交和推送
在提交 DragonBonesCPP 之前,若已经修改过子模块,请务必先提交子模块的修改并推送子模块,然后再提交并推送 DragonBonesCPP 。
删除子模块
为了方便查询,这里摘抄 一文中的移除 Submodule 的方法如下:
1. 删除 git cache 和物理文件夹
以删除 engines/cocos2d-x
为例:
git rm -r --cached engines/cocos2d-x/rm -rf engines/cocos2d-x/
2. 修改配置文件
- 删除
.gitmodules
文件中对应的配置内容; - 删除
.git/config
中的对应 submodule remote 的内容。
3. 提交更改
(全文完)