设为首页 收藏本站
查看: 736|回复: 0

[经验分享] 256code, 生活与技术

[复制链接]

尚未签到

发表于 2018-1-15 06:34:16 | 显示全部楼层 |阅读模式

  GIT 支持子模块,所谓 GIT 子模块,即某个项目需要管理的模块数目太多,而各个模块需要不同的人或团队维护,此时就需要在GIT中引入子模块。GIT 引入子模块后,其本身的上游代码提交历史依然可以保存下来,并且避免了在上游代码发生变更时本地的定制代码归并(Merge)困难。

新建带子模块的项目 PyDemo
  我们举一个简单的例子说明上述问题:假设你开发了一个项目 PyDemo,PyDemo 项目中使用了Leveldb 的 Python 绑定 cpy-leveldb(https://github.com/forhappy/cpy-leveldb),但是需要在定制 cpy-leveldb 的功能,此时你就需要在PyDemo 项目中新建一个子模块 cpy-leveldb,然后修改本地 cpy-leveldb的实现,此时 PyDemo 把它视作一个子模块,当你不在 cpy-leveldb 目录里时并不记录它的内容,取而代之的是,Git 将它记录成来自那个仓库的一个特殊的提交。当你在那个子目录里修改并提交时,子项目会通知那里的 HEAD 已经发生变更并记录你当前正在工作的那个提交
  代码如下:
  

forhappy@forhappy-lenovo:/tmp$ mkdir PyDemo  
forhappy@forhappy
-lenovo:/tmp$ cd PyDemo/  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ ls  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ git init  
Initialized empty Git repository
in /tmp/PyDemo/.git/  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ touch README  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ vim README  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ git add .  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ git ci -m "Initial commit."  
[master (root
-commit)>
1 file changed, 1 insertion(+)  
create mode
100644 README  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ git st  
# On branch master
  
nothing to commit (working directory clean)
  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ git submodule add git@github.com:forhappy/cpy-leveldb.git  
Cloning into
'cpy-leveldb'...  
remote: Counting objects:
888, done.  
remote: Compressing objects:
100% (475/475), done.  

  建立了 PyDemo 项目的子模块后我们查看一下:
  

forhappy@forhappy-lenovo:/tmp/PyDemo$ ls  
cpy
-leveldb  README  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ git st  
# On branch master
  
# Changes to be committed:
  
#   (use
"git reset HEAD <file>..." to unstage)  
#
  
#    new
file:   .gitmodules  
#    new
file:   cpy-leveldb  
#
  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ git add .  
forhappy@forhappy
-lenovo:/tmp/PyDemo$ git ci -m "add submodule cpy-leveldb"  
[master c02fba3] add submodule cpy
-leveldb  

2 files changed, 4 insertions(+)  
create mode
100644 .gitmodules  
create mode
160000 cpy-leveldb  

  首先你注意到有一个.gitmodules文件。这是一个配置文件,保存了子项目 URL 和你拉取到的本地子目录
  

forhappy@forhappy-lenovo:/tmp/PyDemo$ cat .gitmodules  
[submodule
"cpy-leveldb"]  
path
= cpy-leveldb  
url
= git@github.com:forhappy/cpy-leveldb.git  

  尽管 cpy-leveldb 是你工作目录里的子目录,但 GIT 把它视作一个子模块,当你不在该目录里时并不记录它的内容。注意 cpy-leveldb 条目的 160000 模式,这在 GIT 中是一个特殊模式,基本意思是你将一个提交记录为一个目录项而不是子目录或者文件。
  好了,至此一个带子模块的 GIT 仓库就构建完了,你可以在主项目中添加,删除或修改源码,或者在 cpy-leveldb 中定制你自己的功能,两者不会相互影响,各自保持自己的提交记录。

克隆带子模块的项目
  当你克隆一个带子项目的 GIT 项目时,你将得到了包含子项目的目录,但里面没有文件:
  

forhappy@forhappy-lenovo:/tmp/PyDemo-work$ git clone /tmp/PyDemo  
Cloning into
'PyDemo'...  

done.  
forhappy@forhappy
-lenovo:/tmp/PyDemo-work$ ls  
PyDemo
  
forhappy@forhappy
-lenovo:/tmp/PyDemo-work$ cd PyDemo/  
forhappy@forhappy
-lenovo:/tmp/PyDemo-work/PyDemo$ ls  
cpy
-leveldb  README  
forhappy@forhappy
-lenovo:/tmp/PyDemo-work/PyDemo$ cd cpy-leveldb/  
forhappy@forhappy
-lenovo:/tmp/PyDemo-work/PyDemo/cpy-leveldb$ ls  
forhappy@forhappy
-lenovo:/tmp/PyDemo-work/PyDemo/cpy-leveldb$ cd ..  

  此时你需要执行:git submodule init 来初始化你的本地配置文件,另外你还需要执行:git submodule update来从 cpy-leveldb 项目拉取所有数据并检出你上层项目里所列的合适的提交。
  

forhappy@forhappy-lenovo:/tmp/PyDemo-work/PyDemo$ git submodule init  
Submodule
'cpy-leveldb' (git@github.com:forhappy/cpy-leveldb.git) registered for path 'cpy-leveldb'  
forhappy@forhappy
-lenovo:/tmp/PyDemo-work/PyDemo$ git submodule update  
Cloning into
'cpy-leveldb'...  
remote: Counting objects:
888, done.  
remote: Compressing objects:
100% (475/475), done.  

  一个常见问题是当开发者对子模块做了一个本地的变更但是并没有推送到公共服务器。然后他们提交了一个指向那个非公开状态的指针然后推送上层项目。当其他开发者试图运行git submodule update,那个子模块系统会找不到所引用的提交,因为它只存在于第一个开发者的系统中。如果发生那种情况,你会看到类似这样的错误:
  

$ git submodule update  
fatal: reference isn’t a tree: 6c5e70b984a60b3cecd395edd5b48a7575bf58e0
  
Unable to checkout
'6c5e70b984a60b3cecd395edd5ba7575bf58e0' in submodule path 'cpy-leveldb'  


子模块问题
  使用子模块并非没有任何缺点。首先,你在子模块目录中工作时必须相对小心。当你运行git submodule update,它会检出项目的指定版本,但是不在分支内。这叫做获得一个分离的头——这意味着 HEAD 文件直接指向一次提交,而不是一个符号引用。问题在于你通常并不想在一个分离的头的环境下工作,因为太容易丢失变更了。如果你先执行了一次submodule update,然后在那个子模块目录里不创建分支就进行提交,然后再次从上层项目里运行git submodule update同时不进行提交,Git会毫无提示地覆盖你的变更。技术上讲你不会丢失工作,但是你将失去指向它的分支,因此会很难取到。
  为了避免这个问题,当你在子模块目录里工作时应使用 git checkout -b 创建一个分支。当你再次在子模块里更新的时候,它仍然会覆盖你的工作,但是至少你拥有一个可以回溯的指针。
  切换带有子模块的分支同样也很有技巧。如果你创建一个新的分支,增加了一个子模块,然后切换回不带该子模块的分支,你仍然会拥有一个未被追踪的子模块的目录。

本文部分段落参考来源
  Pro Git:http://github.danmarner.com/section/ch6-6/

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-435202-1-1.html 上篇帖子: Git教程 下篇帖子: Elf Sundae's Blog
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表