CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛
CXYVIP官网源码交易平台_网站源码_商城源码_小程序源码平台-丞旭猿论坛

Git Submodule在TypeScript项目中巧用以提高效率

概述什么是子模块有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目 也许是第三方库,或者你独立开发的,用于多个父项目的库 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。

我们举一个例子 假设你正在开发一个网站然后创建了 Atom 订阅 你决定使用一个库,而不是写自己的 Atom 生成代码 你可能不得不通过 CPAN 安装或 Ruby gem 来包含共享库中的代码,或者将源代码直接拷贝到自己的项目中。

如果将这个库包含进来,那么无论用何种方式都很难定制它,部署则更加困难,因为你必须确保每一个客户端都包含该库 如果将代码复制到自己的项目中,那么你做的任何自定义修改都会使合并上游的改动变得困难Git 通过子模块来解决这个问题。

子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立应用场景适用于多个工程存在大量重复代码或逻辑的场景开发中的依赖库特点如果是使用成熟的、长期不迭代的库的话,和引用npm包没有区别

但对于处在开发阶段的库来说,省去了频繁发版的麻烦可以不用考虑编译逻辑使用typescript的项目可以不用考虑 d.ts 文件对于使用方来说省去了频繁更新依赖的麻烦可以直接查看源码开始使用子模块我们将要演示如何在一个被分成一个主项目与几个子项目的项目上开发。

我们首先将一个已存在的 Git 仓库添加为正在工作的仓库的子模块 你可以通过在 git submodule add 命令后面加上想要跟踪的项目的相对或绝对 URL 来添加新的子模块 在本例中,我们将会添加一个名为 “DbConnector” 的库。

$ git submodule add https://github.com/chaconinc/DbConnectorCloning into DbConnector…remote: Counting objects: 11, done.

remote: Compressing objects: 100% (10/10), done.remote: Total 11 (delta 0), reused 11 (delta 0)Unpacking objects: 100% (11/11), done.

Checking connectivity… done.复制代码默认情况下,子模块会将子项目放到一个与仓库同名的目录中,本例中是 “DbConnector” 如果你想要放到其他地方,那么可以在命令结尾添加一个不同的路径。

.gitmodules文件首先应当注意到新的 .gitmodules 文件 该配置文件保存了项目 URL 与已经拉取的本地目录之间的映射:[submodule “DbConnector”]path = DbConnector。

url = https://github.com/chaconinc/DbConnector复制代码如果有多个子模块,该文件中就会有多条记录 要重点注意的是,该文件也像 .gitignore 文件一样受到(通过)版本控制。

它会和该项目的其他部分一同被拉取推送 这就是克隆该项目的人知道去哪获得子模块的原因克隆含有子模块的项目接下来我们将会克隆一个含有子模块的项目 当你在克隆这样的项目时,默认会包含该子模块目录,但其中还没有任何文件:。

$ git clone https://github.com/chaconinc/MainProjectCloning into MainProject…remote: Counting objects: 14, done.

remote: Compressing objects: 100% (13/13), done.remote: Total 14 (delta 1), reused 13 (delta 0)Unpacking objects: 100% (14/14), done.

Checking connectivity… done.$ cd MainProject$ ls -latotal 16drwxr-xr-x 9 schacon staff 306 Sep 17 15:21 .

drwxr-xr-x 7 schacon staff 238 Sep 17 15:21 ..drwxr-xr-x 13 schacon staff 442 Sep 17 15:21 .git-rw-r–r– 1 schacon staff 92 Sep 17 15:21 .gitmodules

drwxr-xr-x 2 schacon staff 68 Sep 17 15:21 DbConnector-rw-r–r– 1 schacon staff 756 Sep 17 15:21 Makefile

drwxr-xr-x 3 schacon staff 102 Sep 17 15:21 includesdrwxr-xr-x 4 schacon staff 136 Sep 17 15:21 scripts

drwxr-xr-x 4 schacon staff 136 Sep 17 15:21 src$ cd DbConnector/$ ls复制代码其中有 DbConnector 目录,不过是空的 你必须运行两个命令:git submodule init 用来初始化本地配置文件,而 git submodule update 则从该项目中抓取所有数据并检出父项目中列出的合适的提交。

$ git submodule initSubmodule DbConnector (https://github.com/chaconinc/DbConnector) registered for path DbConnector

$ git submodule updateCloning into DbConnector…remote: Counting objects: 11, done.remote: Compressing objects: 100% (10/10), done.

remote: Total 11 (delta 0), reused 11 (delta 0)Unpacking objects: 100% (11/11), done.Checking connectivity… done.

Submodule path DbConnector: checked out c3f01dc8862123d317dd46284b05b6892c7b29bc复制代码现在 DbConnector 子目录是处在和之前提交时相同的状态了。

如果你不想在子目录中手动抓取与合并,那么还有种更容易的方式 运行 git submodule update –remote,Git 将会进入子模块然后抓取并更新$ git submodule update –remote DbConnector。

remote: Counting objects: 4, done.remote: Compressing objects: 100% (2/2), done.remote: Total 4 (delta 2), reused 4 (delta 2)

Unpacking objects: 100% (4/4), done.From https://github.com/chaconinc/DbConnector 3f19983..d0354fc master -> origin/master

Submodule path DbConnector: checked out d0354fc054692d3906c85c3af05ddce39a1c0644复制代码克隆 + 初始化不过还有更简单一点的方式。

如果给 git clone 命令传递 –recurse-submodules 选项,它就会自动初始化并更新仓库中的每一个子模块, 包括可能存在的嵌套子模块$ git clone –recurse-submodules https://github.com/chaconinc/MainProject

Cloning into MainProject…remote: Counting objects: 14, done.remote: Compressing objects: 100% (13/13), done.

remote: Total 14 (delta 1), reused 13 (delta 0)Unpacking objects: 100% (14/14), done.Checking connectivity… done.

Submodule DbConnector (https://github.com/chaconinc/DbConnector) registered for path DbConnectorCloning into DbConnector…

remote: Counting objects: 11, done.remote: Compressing objects: 100% (10/10), done.remote: Total 11 (delta 0), reused 11 (delta 0)

Unpacking objects: 100% (11/11), done.Checking connectivity… done.Submodule path DbConnector: checked out c3f01dc8862123d317dd46284b05b6892c7b29bc

复制代码拓展发布子模块改动如果我们在主项目中提交并推送但并不推送子模块上的改动,其他尝试检出我们修改的人会遇到麻烦, 因为他们无法得到依赖的子模块改动那些改动只存在于我们本地的拷贝中为了确保这不会发生,你可以让 Git 在推送到主项目前检查所有子模块是否已推送。

git push 命令接受可以设置为 “check” 或 “on-demand” 的 –recurse-submodules 参数 如果任何提交的子模块改动没有推送那么 “check” 选项会直接使 push 操作失败。

$ git push –recurse-submodules=checkThe following submodule paths contain changes that cannot be found on any remote:

DbConnectorPlease trygit push –recurse-submodules=on-demandor cd to the path and usegit pushto push them to a remote.

复制代码如你所见,它也给我们了一些有用的建议,指导接下来该如何做 最简单的选项是进入每一个子模块中然后手动推送到远程仓库,确保它们能被外部访问到,之后再次尝试这次推送 如果你想要对所有推送都执行检查,那么可以通过设置 git config push.recurseSubmodules check 让它成为默认行为。

另一个选项是使用 “on-demand” 值,它会尝试为你这样做$ git push –recurse-submodules=on-demandPushing submodule DbConnector。

Counting objects: 9, done.Delta compression using up to 8 threads.Compressing objects: 100% (8/8), done.

Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.Total 9 (delta 3), reused 0 (delta 0)To https://github.com/chaconinc/DbConnector

c75e92a..82d2ad3 stable -> stableCounting objects: 2, done.Delta compression using up to 8 threads.Compressing objects: 100% (2/2), done.

Writing objects: 100% (2/2), 266 bytes | 0 bytes/s, done.Total 2 (delta 1), reused 0 (delta 0)To https://github.com/chaconinc/MainProject

3d6d338..9a377d1 master -> master复制代码如你所见,Git 进入到 DbConnector 模块中然后在推送主项目前推送了它 如果那个子模块因为某些原因推送失败,主项目也会推送失败。

子模块遍历有一个 foreach 子模块命令,它能在每一个子模块中运行任意命令 如果项目中包含了大量子模块,这会非常有用例如,假设我们想要开始开发一项新功能或者修复一些错误,并且需要在几个子模块内工作 我们可以轻松地保存所有子模块的工作进度。

$ git submodule foreach git stashEntering CryptoLibraryNo local changes to saveEntering DbConnectorSaved working directory and index state WIP on stable: 82d2ad3 Merge from origin/stable

HEAD is now at 82d2ad3 Merge from origin/stable复制代码然后我们可以创建一个新分支,并将所有子模块都切换过去$ git submodule foreach git checkout -b featureA。

Entering CryptoLibrarySwitched to a new branch featureAEntering DbConnectorSwitched to a new branch featureA

复制代码有用的别名你可能想为其中一些命令设置别名,因为它们可能会非常长而你又不能设置选项作为它们的默认选项 我们在 Git 别名 介绍了设置 Git 别名, 但是如果你计划在 Git 中大量使用子模块的话,这里有一些例子。

$ git config alias.sdiff !”git diff && git submodule foreach git diff”$ git config alias.spush push –recurse-submodules=on-demand

$ git config alias.supdate submodule update –remote –merge复制代码这样当你想要更新子模块时可以简单地运行 git supdate,或 git spush 检查子模块依赖后推送。

从子目录切换到子模块另一个主要的告诫是许多人遇到了将子目录转换为子模块的问题 如果你在项目中已经跟踪了一些文件,然后想要将它们移动到一个子模块中,那么请务必小心,否则 Git 会对你发脾气 假设项目内有一些文件在子目录中,你想要将其转换为一个子模块。

如果删除子目录然后运行 submodule add,Git 会朝你大喊:$ rm -Rf CryptoLibrary/$ git submodule add https://github.com/chaconinc/CryptoLibrary

CryptoLibrary already exists in the index复制代码你必须要先取消暂存 CryptoLibrary 目录 然后才可以添加子模块:$ git rm -r CryptoLibrary。

$ git submodule add https://github.com/chaconinc/CryptoLibraryCloning into CryptoLibrary…remote: Counting objects: 11, done.

remote: Compressing objects: 100% (10/10), done.remote: Total 11 (delta 0), reused 11 (delta 0)Unpacking objects: 100% (11/11), done.

Checking connectivity… done.复制代码现在假设你在一个分支下做了这样的工作 如果尝试切换回的分支中那些文件还在子目录而非子模块中时——你会得到这个错误:$ git checkout master。

error: The following untracked working tree files would be overwritten by checkout: CryptoLibrary/Makefile

CryptoLibrary/includes/crypto.h …Please move or remove them before you can switch branches.Aborting

复制代码你可以通过 checkout -f 来强制切换,但是要小心,如果其中还有未保存的修改,这个命令会把它们覆盖掉$ git checkout -f masterwarning: unable to rmdir CryptoLibrary: Directory not empty。

Switched to branch master复制代码当你切换回来之后,因为某些原因你得到了一个空的 CryptoLibrary 目录,并且 git submodule update 也无法修复它 你需要进入到子模块目录中运行 git checkout . 来找回所有的文件。

你也可以通过 submodule foreach 脚本来为多个子模块运行它要特别注意的是,近来子模块会将它们的所有 Git 数据保存在顶级项目的 .git 目录中,所以不像旧版本的 Git,摧毁一个子模块目录并不会丢失任何提交或分支。

删除子模块# 逆初始化模块,执行后可发现模块目录被清空$ git submodule deinit # 清除暂存$ git rm –cached # 查询暂存区当前的内容$ git ls-files –stage | grep 160000

# 删除目录$ rm -rf # 删除项目中子模块设置$ vi .git/config 删掉submodule信息$ rm -rf .git/modules/复制代码实践Step 1

根目录下创建 .gitmodules 文件

.gitmodules 文件中设置子模块 path、url、branch 信息

Step 2VSCode > Source Control 中可以看到“主项目”和“子模块”,可确认子模块分支或切换至其他分支。

Step 3安装依赖之后执行子模块初始化命令 git submodule init && git submodule update –remote

Step 4子模块目录下出现对应文件

Step 5子模块的变更记录可以在子模块的 Source Control 中确认

主项目中只标记子模块有发生变化,但并不显示具体内容

Step 6gitlab中会用特殊的图标标记子模块目录,点击可移动至对应项目的对应提交

其他注意事项初始状态为该分支最近一次提交

需切换至对应分支

一些建议分支名以版本号命名,如 0.0.1为了可以正常克隆项目,开发者需要同时拥有主项目和子模块的权限但是为了限制随意修改代码,只赋予不需要修改子模块代码的开发者reporter权限可单独创建打包项目,发布npm包提供给第三方

作者:Finos链接:https://juejin.im/post/5e9e964451882573bc7c2908来源:掘金著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

© 版权声明
THE END
喜欢就支持一下吧
点赞0赞赏 分享
相关推荐
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容