1.git submodule
什么是git submodule?
有2个概念:主项目、submodule(子模块)。这两者各自都是完整的 Git 仓库。git submodule就是在一个主项目中引入另一个git仓库作为子模块。
如何给一个项目添加submodule?
1.进入主项目A目录下,添加B仓库作为子模块
git submodule add {clone B仓库的地址}
执行完成后在项目A中会生成一个.gitmodules文件,该文件记录了主模块和子模块之间的引用关系
如何初始化项目的submodule?
(常用于新拉取一个带有submodule的项目的时候)
1.先git clone 主项目仓库,这时候submodule的文件夹都是空的。
2.执行git submodule update --init --recursive,执行完成以后子模块就有内容了
关于submodule的代码更新和提交
方式一:
cd {子模块名称} 进入子模块的目录,正常的执行git 命令
方式二:
前缀git submodule foreach命令即可操作子模块
比如:git submodule foreach git pull
推荐使用vscode的git工具,可以很方便的进行多个工程的代码版本管理
为了方便,我们可以增加一条自定义命令来拉取两个工程的代码:"update": "git pull && git submodule foreach git pull",以后每次执行npm run update即可一次性更新主模块和子模块
注意,有个坑
submodule项目和它的父项目本质上是2个独立的git仓库。只是父项目存储了它依赖的submodule项目的版本号信息而已。如果别人更新了submodule,然后更新了父项目中依赖的版本号。你需要在git pull之后,调用 git submodule update来更新submodule信息。
默认git submodule update并不会将submodule切到任何branch,所以,默认下submodule的HEAD是处于游离状态的(‘detached HEAD’ state)。所以在修改前,记得一定要确认当前子模块的分支,然后才能做修改和提交。
如果你不慎忘记切换到自己的分支分支,又做了提交,可以用cherry-pick命令挽救。具体做法如下:
1.用 git checkout 将HEAD从游离状态切换到 自己的 分支, 这时候,git会报Warning说有一个提交没有在branch上,记住这个提交的change-id(假如change-id为 aaaa)
2.用 git cherry-pick aaaa 来将刚刚的提交作用在 自己的 分支上
3.用 git push 将更新提交到远程版本库中
2.git subtree
git subtree add
使用场景: 添加subtree
完整命令:git subtree add --prefix={目录路径} xxxx.git branch --squash
git subtree pull
使用场景: subtree代码有更新,需要同步到本工程
完整命令: git subtree pull --prefix={目录路径} xxxx.git branch --squash
注意:不加--squash可能会报错
git subtree push
使用场景: 在父工程修改了subtree的内容,需要把修改同步到subtree的git仓库
完整命令: git subtree push --prefix={目录路径} xxxx.git branch
但是会很慢,subtree push实际上是遍历本工程每一次提交,把提交文件涉及到subtree目录的挑出来,同步到subtree工程,如果提交有很多,遍历提交的过程是有严重的性能问题的,在2.19版本以前的git是可以执行的,但是很慢,在2.19以上的版本,会直接抛出异常。
git subtree split
使用场景: 提升subtree push效率
完整命令: git subtree split --prefix={目录路径} --rejoin
执行split命令后,会看到主工程的提交记录,产生了一个新的分支,且这个分支和subtree push操作的逻辑一样,只把涉及subtree目录的提交摘出来了,最终这个分支合并到原分支,产生了一个Split xxxxx的提交记录。
后续再执行subtree push操作,git只会检索split以后的提交,达到减少检索次数的目的,提升push性能。
git rm -r
使用场景: 在父工程中移除subtree,或者切换subtree的分支。如果要切换subtree的分支,就需要用该命令先移除,后执行git subtree add添加
注意:执行该操作前一定要确保subtree的代码已经提交,否则移除等于直接本地删除,会丢失代码
简化操作
在 subtree 相关命令经常会用到 每次都写地址还是比较麻烦,这里可以用 git remote 命令简化写法,为这个远程地址定义一个 “别名”:
git remote add common xxxx.git
比如使用 subtree push 的时候就可以使用如下命令:
git subtree push --prefix={目录路径} develop