git日常使用中,基本都是一个项目一个Git仓库的形式,那么当我们的代码中碰到了业务级别的需要复用的代码,我们一般怎么做呢?
比如:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。
所以需要提取一个公共的类库提供给多个项目使用,但是这个library怎么和git在一起方便管理呢?
现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。
我们大致的考虑一下,一般有两种方案:
但是:两个程序中有部分页面或功能是重叠的,在前端领域,比如AntDesign、element-UI,react 、vue、angular版本样式是一样的,只是组件不同。
开发过程中重叠部分如果开发两套代码会浪费不少的人力。
个人推荐选用Git子模块的方式进行开发,父级仓库依赖两个公共的子模块,子模块本身和父级仓库一同进行开发,可避免了版本问题和重复开发的问题。
面对比较复杂的项目,我们有可能会将代码根据功能拆解成不同的子模块。主项目对子模块有依赖关系,却又并不关心子模块的内部开发流程细节。
大致结构可能是这样
project
|--moduleA
|--submoduleC
|--submoduleD
|--moduleB
project和ABCD各个模块中,CD在不同的git仓库中,这时,就需要使用git的的模块功能
Git 通过子模块来解决这个问题。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。
通俗上的理解, 一个Git仓库下面放了多个其他的Git仓库,其他的Git仓库就是我们父级仓库的子仓库。
git Submodule 是一个很好的多项目使用共同类库的工具,他允许类库项目做为repository,子项目做为一个单独的git项目存在父项目中,子项目可以有自己的独立的commit,push,pull。而父项目以Submodule的形式包含子项目,父项目可以指定子项目header,父项目中会的提交信息包含Submodule的信息,再clone父项目的时候可以把Submodule初始化。
可以端详官网:https://git-scm.com/book/zh/v2/Git-工具-子模块
多个父级仓库都依赖同一个子仓库,但是子仓库自身不单独进行修改,而是跟随父级项目进行更新发布,其他依赖子仓库的项目只负责拉取更新即可。
Git子模块允许我们将一个或者多个Git仓库作为另一个Git仓库的子目录,它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。
在Git 中你可以用子模块submodule来管理这些项目,submodule允许你将一个Git 仓库当作另外一个Git 仓库的子目录。这允许你克隆另外一个仓库到你的项目中并且保持你的提交相对独立。
git clone https://github.com/zhoulujun/zhoulujun.cn-phpcms.git zhoulujun
cd zhoulujun
git submodule add tools
git submodule add https://github.com/zhoulujun/zhoulujun.cn-tools-vue.git tools-vue
添加子模块后运行git status, 可以看到目录有增加1个文件.gitmodules, 这个文件用来保存子模块的信息。
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: .gitmodules
new file: assets
使用git init --bare在本地创建两个裸仓库,分别表示主仓库和依赖的子仓库,我们将主仓库命名为main,依赖的子仓库命名为lib, git subtree使用同样的初始化方法,下文不再赘述。
--recursive表示递归地克隆git_parent依赖的所有子版本库。
上面介绍的git submodule是Git自带的原生功能,我们接下来将要介绍的git subtree则是由第三方开发者贡献的contrib script,Git本身并不提供git subtree命令,contrib中包含一些实验性的第三方工具,由各自的作者进行维护。
同时这也让我们认识到git subtree不是Git原生支持的命令,而是第三方开发者通过Git的底层命令写出的一个高层次脚本,所以它是可以由基础的Git命令来实现的。
subtree与submodule的作用是一样的,但是subtree出现得比submodule晚,它的出现是为了弥补submodule存在的问题:
subtree则可以实现双向数据修改。官方推荐使用subtree替代submodule。
这里就先不提了
注意:**必须在 `component` 的父级目录执行**,使用起来还不是很方便。
submodule可以一起clone出来,只需添加--recursive递归参数就可以了,而subtree并不行,只能手动添加
个人使用submodule习惯了,所以天然觉得subtree复杂难用===难道就像用惯了intelliJ,就没有心思去用VScode了,哈哈!
有人对 submodule 和 subtree 的区别做的一个总结还是挺形象的: submodule is link; subtree is copy 。
更多的推荐阅读: Git应用详解第十讲:Git子库:submodule与subtree https://blog.csdn.net/qq_43425487/article/details/105632114
如果不是很了解底层原理,很可能会导致使用子仓库出现云里雾里的现象,搞不清楚是父级仓库先提交,还是子仓库先提交
我们知道Git底层大致依赖了四种对象,构成了Git对于文件内容追踪的基础:
更加详细的内容请参考《深入理解Git》
我们此处需要依赖一个print_all_object的工具函数,它会帮助我们将git仓库下的这四种对象按照反向提交历史的排序展现出来,可以将它放在环境变量下方便全局使用:
#!/bin/bash
print_all_object() {
for object in `git rev-list --objects --all | cut -d ' ' -f 1`; do
echo 'SHA1: ' $object
git cat-file -p $object
echo '-------------------------------'
done
}
print_all_object
我们在main仓库下执行print_all_object:
# 此时处于我们刚对子模块提交的那个时间点
# 对部分长的hash进行了截取处理,不影响阅读观感
print_all_object
SHA1: a1cfd26e
tree c77ba9c2
parent ab118b8
feat: 增加子仓库依赖
-------------------------------
SHA1: ab118b8
tree f5771cd
feat: 父级仓库创建index.js
-------------------------------
SHA1: c77ba9c2
100644 blob d8c9fb4 .gitmodules
100644 blob ddd81ae index.js
160000 commit 40f8536 lib
-------------------------------
SHA1: d8c9fb4
[submodule "lib"]
path = lib
url = /path/to/repos/lib.git
-------------------------------
SHA1: ddd81ae
console.log('main');-------------------------------
SHA1: f5771cd
100644 blob ddd81ae index.js
-------------------------------
index.js文件是blob对象,对应的file mode是100644,但是对于lib子仓库的确是一个commit对象, file mode为160000,这是Git中一种特殊的模式,表明我们是将一次提交的commit记录在Git当中,而非将它记录成一个子目录或者文件。
而这正式git submodule的核心原理,Git在处理submodule引用的时候,并不会去扫描子仓库下的文件的变化,而是取子仓库当前的HEAD指向的commit的hash值,当我们对子仓库进行了更改后,Git获取到子模块的commit值发生变化,从而记录了这个Git指针的变化。
在暂存区所以我们才发现了new commits这种提示语,Git并不关心子模块的文件如何变化,我只需要在当前提交中记录子模块的commit的hash值即可,之后我们从父级仓库拉取子仓库的时候,Git拉取了本次提交记录中的子模块的hash值对应的提交,就还原了我们的整个仓库的代码。
虽然使用git submodule为我们的开发带来了很多便利,但是随之而来也会导致一些比较容易犯的错误,整理出来,防止大家采坑:
参考文章:
Git submodule 子模块的管理和使用 https://www.jianshu.com/p/9000cd49822c
使用Git Submodule管理子模块 https://segmentfault.com/a/1190000003076028
Git子仓库深入浅出 https://juejin.im/post/6844904034722119694
子模块 http://gitbook.liuhui998.com/6_2.html
使用git subtree & submodule管理多个子项目 https://www.jianshu.com/p/84e34ac318e4
Git应用详解第十讲:Git子库:submodule与subtree https://blog.csdn.net/qq_43425487/article/details/105632114
git submoudle vs git subtree https://efe.baidu.com/blog/git-submodule-vs-git-subtree/
转载本站文章《Git 工具 - 子模块: submodule与subtree的使用》, 请注明出处:https://www.zhoulujun.cn/html/tools/VCS/git/8566.html
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。