-
Notifications
You must be signed in to change notification settings - Fork 227
Manage a git library with submodules
管理带有子模块的git库(DragonBonesCPP)
Manage a git library with submodules.
DragonBonesCPP 是一个包含子模块的库,在 clone/commit/push 的时候需要一些额外的操作。
本文将描述这些操作。
限(wei)于(le)篇(tou)幅(lan),请自行学习下面的内容:
git clone --recursive git@github.com:DragonBones/DragonBonesCPP.git
使用这个方法,将会自动 clone 该项目下的所有子模块。这其实是最简单的方法了。
为什么说它令人蛋碎呢?因为 DragoneBones 中包含的 engines/cocos2d-x 子模块也包含子模块。
这样就出现了嵌套子模块,一个 cocos2d-x 的所有历史加起来就超过1G了,再加上子模块的所有历史,这就……。
为了避免蛋碎的问题,我们换一个方法,可是蛋疼是免不了了。
# git clone git@github.com:DragonBones/DragonBonesCPP.git
Cloning 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 init
Submodule 'cocos2d-x' (git@github.com:DragonBones/cocos2d-x.git) registered for path 'engines/cocos2d-x'
# DragonBonesCPP git:(master) > git submodule update
Cloning 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 项目目前有2个分支,master 和 dev ,区别如下:
以对 cocos2d-x 引擎的支持为例:
在开发的过程中,我们经常需要切换分支。例如对 cocos2d-x 2.x 的相关功能进行修改后(位于master分支),希望切换到 cocos2d-x 3.x 的另一些功能进行修改。
这种情况下,我们一般使用 git checkout 来切换分支。于是,奇怪的事情发生了:
# DragonBonesCPP git:(master) > git checkout dev
M engines/cocos2d-x
Switched 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 diff
diff --git a/engines/cocos2d-x b/engines/cocos2d-x
index 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 master
nothing 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 develop
Switched 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 文件可以解决这个问题,可参阅这里: Merge-Strategies 。
为了解决这个矛盾,我已在 .gitattributes 中将 renderer 和 engines 目录排除,在合并的时候,它们将保存各自的版本。
若有更深入的需求,例如 renderer 中的某些渲染器需要合并而有些不要,则后续进一步处理。
在提交 DragonBonesCPP 之前,若已经修改过子模块,请务必先提交子模块的修改并推送子模块,然后再提交并推送 DragonBonesCPP 。