通过 GitExtensions 来使用 Git 子模块功能

通过 GitExtensions 来使用 Git 子模块功能

通过 GitExtensions 来使用 Git 子模块功能

独立观察员 2021 年 9 月 5 日

 

一、前言

众所周知,编程,尤其是面向对象编程的一个重要思想就是 “封装”,可重用的代码逻辑封装为方法,使用于同一业务的方法封装为类,功能相关的类封装到一个类库中,等等等等。在 .NET 中,一个项目最终生成一个类库(DLL),当然,这个项目可能会引用其它项目或类库(所以生成路径下可能好多 .dll)。而我们用开发工具 Visual Studio 打开的一般是个解决方案,解决方案中一般包含了 1~n 个项目。另外,现在的开发流程中,一般都会使用版本控制系统,比较流行的就是 Git 和 SVN,就拿 Git 来说,一般我们会将一个解决方案放在一个代码仓库中,然后托管在提供 Git 代码仓库托管服务的网站上,比较流行的就是 GitHub 和 Gitee。

 

当我们有两个以上的相互独立的解决方案要共用一个类库项目时,一般有以下几种方法:

1、多个解决方案分别引用相同路径的项目;(缺点:只适用于代码仅在本地维护的场景)

2、将该项目代码分别拷贝到各解决方案目录下进行引用;(缺点:容易造成版本不一致的问题)

3、将该项目生成为库文件(如 .dll 文件)然后分别引用;(缺点:同样存在版本问题,且不方便进行代码修改)

4、将该项目打包上传到公共或私有的 NuGet 库中,然后引用;(缺点:适用于提供给其他人使用的场景,不利于代码的修改学习)

 

可以看到,以上方法都有这样那样的缺点,那么有没有其它比较好的方法呢?答案就是使用本文将要介绍的 Git 子模块submodule)功能。

 

既然叫 Git 子模块功能,那么自然是和 Git 深度绑定的。正所谓工欲善其事必先利其器,我先来推荐一个 Git 工具 ——GitExtensionsGitExtensions 是一款类似于 TortoiseGit 的 Git 图形化工具,安装之后既可以当作桌面软件使用,也可以再安个 VS 插件,以便直接在 VS 中打开操作界面。使用方法可略微看看本人五、六年前写的文章《使用 Git Extensions 简单入门 Git》,区别是,现在的版本没有整合 Git 和 KDiff3 了,需要自己安装,然后 VS 插件可在微软网站上下载。

 

二、Git 子模块

那么安装好了之后,如何添加 Git 子模块呢?先不急,我们先来看看添加过 Git 子模块后的目录中会有什么变化:

通过 GitExtensions 来使用 Git 子模块功能插图

 

可以看到,就是多了个 .gitmodules 文件,打开看看内容吧:

通过 GitExtensions 来使用 Git 子模块功能插图1

 

文件内容显示,当前有两个子模块,分别列出了模块名、本地存放的目录、远程仓库地址、分支名。理论上,添加的话可以直接修改这个文件,当为了保险起见(不知道 Git 的内部操作),建议还是通过命令或图形界面来维护 Git 子模块。命令的方式可以参考网上的文章《git submodule 的使用(.gitmodules 文件子模块加载)》,本文就不再赘述了。下面来介绍如何使用 GitExtensions 进行相关的图形化界面操作。

 

首先,在 Git 文件夹中右键,点击 “GitExt Open repository”:

通过 GitExtensions 来使用 Git 子模块功能插图2

 

在打开的 Git 仓库管理界面,点击 档案库 --> 管理子模块:

通过 GitExtensions 来使用 Git 子模块功能插图3

 

可以看到两个现存的子模块的信息,点击 新增子模块 可进行新增,填上 公共仓库路径、本地路径、分支 即可新增了,就是这么简单:

通过 GitExtensions 来使用 Git 子模块功能插图4

 

另外三个功能是 同步、更新、移除,更新和移除很好理解,同步大概就是将子模块中修改的内容提交推送吧,我也没用过,我一般就是进入子模块目录,将其当做独立的 Git 目录来进行提交推送的。

 

当我们克隆带有 Git 子模块的仓库时要记得勾上 “初始化所有子模块” 选项,不然的话克隆结束之后子模块目录不会出现:

通过 GitExtensions 来使用 Git 子模块功能插图5

 

我们打开子模块的目录,和普通 Git 目录相比,就是没有了 .git 文件夹,而是一个 .git 文件,里面写明了当前模块的 git 存储位置:

通过 GitExtensions 来使用 Git 子模块功能插图6

 

三、子模块更改提交

下面来说说常规的使用方法,我们先在子模块 WPFTemplateLib 的目录中新建一个测试文件:

通过 GitExtensions 来使用 Git 子模块功能插图7

 

然后在 GitExtensions 的主界面就能看到检测出变动了,提示说有一项可以提交,而且标示出了是在子模块中产生的变动:

通过 GitExtensions 来使用 Git 子模块功能插图8

 

可以直接点击提交,不过提交信息不是很明确:

通过 GitExtensions 来使用 Git 子模块功能插图9

 

我一般选择切到子模块界面进行提交,切换方法就是点击状态栏一个像鱼雷一样的图标:

通过 GitExtensions 来使用 Git 子模块功能插图10

 

这样提交信息就比较清晰了:

通过 GitExtensions 来使用 Git 子模块功能插图11

 

刚才如果只是点的 “提交”,那就再 “推送” 一下:

通过 GitExtensions 来使用 Git 子模块功能插图12

 

推送完成之后,看分支图上还是有一个虚线框的分支标记,这就是说明父工程还是引用的上个版本的本模块:

通过 GitExtensions 来使用 Git 子模块功能插图13

 

我们再切换到父工程:

通过 GitExtensions 来使用 Git 子模块功能插图14

 

可以看到还是有可提交标志,这里其实是提交对子模块的引用信息(引用哪个提交版本)的更改:

通过 GitExtensions 来使用 Git 子模块功能插图15

 

提交界面如下(注意和之前的进行对比),显示了新旧的版本信息:

通过 GitExtensions 来使用 Git 子模块功能插图16

 

提交(未推送)之后再切到子模块,虚框分支标记就消失了:

通过 GitExtensions 来使用 Git 子模块功能插图17

 

四、更新子模块

接下来演示一下更新子模块的操作,我们先复位一下父工程,在上个提交上右键 --> 复位当前分支到此处:

通过 GitExtensions 来使用 Git 子模块功能插图18

 

复位方式这里选择 混合模式:

通过 GitExtensions 来使用 Git 子模块功能插图19

 

回到了如下状态:

通过 GitExtensions 来使用 Git 子模块功能插图20

 

由于我们之前提交子模块时勾选了 “在父工程中载入” 选项,现在我们先在提交界面,右键 --> 更新子模块:

通过 GitExtensions 来使用 Git 子模块功能插图21

 

由于父工程对子模块的引用并未更改(提交),所以此处更新子模块后,将会将子模块的提交索引复位(重新指向上个版本):

通过 GitExtensions 来使用 Git 子模块功能插图22

 

这样父工程恢复如初:

通过 GitExtensions 来使用 Git 子模块功能插图23

 

子模块的当前版本也复位了:

通过 GitExtensions 来使用 Git 子模块功能插图24

 

不过这样操作只是通过父工程进行强行复位,可以看到上图中分支的下拉框已经变成 (no branch) 了,这是不好的。正常操作应该是对子模块进行复位,我们先重新切回 master 分支:

通过 GitExtensions 来使用 Git 子模块功能插图25

 

然后使用 “复位当前分支到此处” 功能:

通过 GitExtensions 来使用 Git 子模块功能插图26

 

这次使用 “硬模式”,当作什么都没有发生过:

通过 GitExtensions 来使用 Git 子模块功能插图27

 

情况如下:

通过 GitExtensions 来使用 Git 子模块功能插图28

 

这种情况就像是,公共库在别的地方有了新版本,而我这个项目目前在用旧版本,现在可以选择保持使用旧版本,也可以选择更新到新版本。

 

选择旧版本的话,就是 “更新子模块” 或者什么都不操作(因为克隆的时候已经更新过了):

通过 GitExtensions 来使用 Git 子模块功能插图29

 

选择新版本的话,就是对子模块进行拉取操作:

通过 GitExtensions 来使用 Git 子模块功能插图30

 

然后父工程界面就会出现熟悉的标志:

通过 GitExtensions 来使用 Git 子模块功能插图31

 

当然,实际上你可以选择任何版本。其它的就大家自己探索吧。

 

五、[附] 去除最近的提交记录

大家也看到了,这次我为了写这篇文章,在项目中提交推送了一条无用的信息:

通过 GitExtensions 来使用 Git 子模块功能插图32

 

那么有没有方法去除呢?实际上之前也有过一篇文章《Git 图形化操作之合并提交记录》,不过那个是合并,最终还是有一条记录的,这次是要删除。概括说来,方法就是 复位 强制推送

 

首先是复位(复位当前分支到此处):

通过 GitExtensions 来使用 Git 子模块功能插图33

 

然后是强制推送(这里使用 强制租用 就行了):

通过 GitExtensions 来使用 Git 子模块功能插图34

 

然后就行了:

通过 GitExtensions 来使用 Git 子模块功能插图35

 

Gitee 上也是正常的:

通过 GitExtensions 来使用 Git 子模块功能插图36

 

好了,全文完,祝大家生活愉快。

 

 

发表评论