首页 > Linux, 挨踢(IT), 日拱一卒 > Git Submodule 使用简介

Git Submodule 使用简介

2016年3月5日 发表评论 阅读评论 1,352 人阅读    

D瓜哥从去年开始,将所有的笔记都整合到了自建的 Wiki 中。整理分析,确实方便很多。

最近有两个部分,比较独立,自成系统。其中,有一个模块还考虑和其他小伙伴合作来搞。所以,就将这两部分抽取出来,独立成单独的项目来维护。但是,为方便查看和随时随地同步更新,正好可以使用 Git Submodule 特性。

另外,还有一种场景:开发的项目使用了第三方或者公司的基础库,使用同一个版本库肯定不合适,也不现实,这时就必须使用子模块来搞。

对 Git 不了解的,可以参考D瓜哥以前的文章:Git&Github社区化协作使用指南。下面,D瓜哥带领大家来学习一下 git submodule 的简单实用方法。

添加子模块

从新建一个项目,或者从远处服务器上克隆一个项目,作为“顶级项目”。这里,D瓜哥就从 Github 上新建一个项目,然后再克隆下来:

1➜  /Users/diguage  git clone git@github.com:diguage/parent.git
2 
3Cloning into 'parent'...
4remote: Counting objects: 5, done.
5remote: Compressing objects: 100% (5/5), done.
6remote: Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
7Receiving objects: 100% (5/5), 4.59 KiB | 0 bytes/s, done.
8Checking connectivity... done.

进入刚克隆下来的项目,我们来添加子模块。这里的子模块就必须从远处服务器上克隆了。另外,子模块可以放在项目的任意目录下,并且可以根据自己的需要重命名。D瓜哥这里这是为了方便演示,所以就直接放在子目录了。进入顶级项目,我们先看一下版本库的状态:

1➜  /Users/diguage cd parent
2 
3➜  /Users/diguage/parent git:(master) git status
4 
5On branch master
6Your branch is up-to-date with 'origin/master'.
7nothing to commit, working directory clean

这里提示,项目中没有任何需要提交的东西。下面,我们开始添加子模块:

1➜  /Users/diguage/parent git:(master) git submodule add git@github.com:diguage/child.git
2 
3Cloning into 'child'...
4remote: Counting objects: 5, done.
5remote: Compressing objects: 100% (5/5), done.
6remote: Total 5 (delta 0), reused 0 (delta 0), pack-reused 0
7Receiving objects: 100% (5/5), 4.63 KiB | 0 bytes/s, done.
8Checking connectivity... done.

这时,再看一下版本库的状态:

1➜  /Users/diguage/parent git:(master) ✗ git status
2On branch master
3Your branch is up-to-date with 'origin/master'.
4Changes to be committed:
5  (use "git reset HEAD <file>..." to unstage)
6 
7    new file:   .gitmodules
8    new file:   child

这时,我们看到,除了刚刚添加的 child 模块外,还多了一个 .gitmodules 文件。这个文件就是用于记录子模块的路径已经远程版本库地址的地方。这两个文件处于待提交的状态。下面把这个修改提交一下。

01➜  /Users/diguage/parent git:(master) ✗ git commit -am "增加子模块"
02 
03[master a05bfe0] 增加子模块
04 2 files changed, 4 insertions(+)
05 create mode 100644 .gitmodules
06 create mode 160000 child
07 
08 
09➜  /Users/diguage/parent git:(master) git push origin master
10 
11Counting objects: 3, done.
12Delta compression using up to 8 threads.
13Compressing objects: 100% (3/3), done.
14Writing objects: 100% (3/3), 452 bytes | 0 bytes/s, done.
15Total 3 (delta 0), reused 0 (delta 0)
16To git@github.com:diguage/parent.git
17   e56cd5a..a05bfe0  master -> master

这时,大家可以登录到 Github 或者其他的版本库服务器上看一下项目的状态。D瓜哥就不贴图了。

至此,添加子模块的工作已经完成。下面,我们来看一看如何更新。

更新子模块

当我们添加完子模块后,过段时间后,子模块有更新,这时候,我们就需要更新了。我们来看一下如何更新。

方式一

这个方式略微显得有的“笨拙”,但是大智若愚,大巧若拙,万变不离其宗。最笨的招数也许也是最实用的招数。扯了这么多,其实很简单,就是进入到每一个子模块,执行 git pull origin master

01➜  /Users/diguage/parent git:(master) cd child
02 
03➜  /Users/diguage/parent/child git:(master) git pull origin master
04 
05remote: Counting objects: 3, done.
06remote: Compressing objects: 100% (3/3), done.
07remote: Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
08Unpacking objects: 100% (3/3), done.
09From github.com:diguage/child
10 * branch            master     -> FETCH_HEAD
11   d4ec39a..1b855a4  master     -> origin/master
12Updating d4ec39a..1b855a4
13Fast-forward
14 README.md | 3 +++
15 1 file changed, 3 insertions(+)

这时,我们再进入到顶级项目中,查看一下项目状态:

01➜  /Users/diguage/parent/child git:(master) cd ..
02 
03➜  /Users/diguage/parent git:(master) ✗ git status
04 
05On branch master
06Your branch is up-to-date with 'origin/master'.
07Changes not staged for commit:
08  (use "git add <file>..." to update what will be committed)
09  (use "git checkout -- <file>..." to discard changes in working directory)
10 
11    modified:   child (new commits)
12 
13no changes added to commit (use "git add" and/or "git commit -a")

这里可以看到明显的提示,在项目有一个新的提交。为什么会这样呢?其实,Git 在顶级项目中记录了一个子模块的提交日志的指针,用于保存子模块的提交日志所处的位置,以保证无论子模块是否有新的提交,在任何一个地方克隆下顶级项目时,各个子模块的记录是一致的。避免因为所引用的子模块不一致导致的潜在问题。如果我们更新了子模块,我们需要把这个最近的记录提交到版本库中,以方便和其他人协同。这也是刚刚添加完子模块后还要在顶级项目中提交一次的原因。

01➜  /Users/diguage/parent git:(master) ✗ git commit -am "更新子模块"
02 
03[master 5ac4dbb] 更新子模块
04 1 file changed, 1 insertion(+), 1 deletion(-)
05 
06 
07➜  /Users/diguage/parent git:(master) git push origin master
08 
09Counting objects: 2, done.
10Delta compression using up to 8 threads.
11Compressing objects: 100% (2/2), done.
12Writing objects: 100% (2/2), 259 bytes | 0 bytes/s, done.
13Total 2 (delta 1), reused 0 (delta 0)
14To git@github.com:diguage/parent.git
15   a05bfe0..5ac4dbb  master -> master

这里D瓜哥再多说一句:进入子模块目录后,你就当做这是一个独立的项目,可以正常进行一个普通 Git 项目所执行的任何操作。更新完正常的修改、添加任务后,把所做的修改提交,然后推送到远处版本库上。然后,如果需要记得在顶级项目中,也做一次提交,修改一下顶级项目所引用的子模块的提交日志的“指针”。

克隆项目

当多人合作搞一个项目,或者需要同步公司电脑的代码到家里电脑上,就需要从远处版本库上克隆项目代码。这时,可以使用两种方式。

方式一

古语有云:由俭入奢易,由奢入俭难。所以,D瓜哥决定先从比较麻烦的方式入手。下面开始:

01➜  /Users/diguage  git clone git@github.com:diguage/parent.git  # 第一步
02 
03Cloning into 'parent'...
04remote: Counting objects: 10, done.
05remote: Compressing objects: 100% (9/9), done.
06remote: Total 10 (delta 2), reused 5 (delta 1), pack-reused 0
07Receiving objects: 100% (10/10), 5.11 KiB | 0 bytes/s, done.
08Resolving deltas: 100% (2/2), done.
09Checking connectivity... done.
10 
11 
12➜  /Users/diguage  cd parent
13 
14 
15➜  /Users/diguage/parent git:(master) git submodule update --init --recursive  # 第二步
16 
17Submodule 'child' (git@github.com:diguage/child.git) registered for path 'child'
18Cloning into 'child'...
19remote: Counting objects: 8, done.
20remote: Compressing objects: 100% (8/8), done.
21remote: Total 8 (delta 2), reused 0 (delta 0), pack-reused 0
22Receiving objects: 100% (8/8), 4.91 KiB | 0 bytes/s, done.
23Resolving deltas: 100% (2/2), done.
24Checking connectivity... done.
25Submodule path 'child': checked out '1b855a4987b44e7530dbd9904dee089fb31f3525'
26 
27 
28➜  /Users/diguage/parent git:(master) cd child
29 
30 
31➜  /Users/diguage/parent/child git:((1b855a4...)) git status # 第三步
32 
33HEAD detached at 1b855a4
34nothing to commit, working directory clean
35 
36 
37➜  /Users/diguage/parent/child git:((1b855a4...)) git checkout master # 第四步
38 
39Switched to branch 'master'
40Your branch is up-to-date with 'origin/master'.

这里需要大概四步,确实挺复杂。下面我们来看一看稍微简单一点的。

方式二

01➜  /Users/diguage  git clone --recursive git@github.com:diguage/parent.git  # 第一步
02 
03Cloning into 'parent'...
04remote: Counting objects: 10, done.
05remote: Compressing objects: 100% (9/9), done.
06remote: Total 10 (delta 2), reused 5 (delta 1), pack-reused 0
07Receiving objects: 100% (10/10), 5.11 KiB | 0 bytes/s, done.
08Resolving deltas: 100% (2/2), done.
09Checking connectivity... done.
10Submodule 'child' (git@github.com:diguage/child.git) registered for path 'child'
11Cloning into 'child'...
12remote: Counting objects: 8, done.
13remote: Compressing objects: 100% (8/8), done.
14remote: Total 8 (delta 2), reused 0 (delta 0), pack-reused 0
15Receiving objects: 100% (8/8), 4.91 KiB | 0 bytes/s, done.
16Resolving deltas: 100% (2/2), done.
17Checking connectivity... done.
18Submodule path 'child': checked out '1b855a4987b44e7530dbd9904dee089fb31f3525'
19 
20 
21➜  /Users/diguage  cd parent/child
22 
23 
24➜  /Users/diguage/parent/child git:((1b855a4...)) git status # 第二步
25 
26HEAD detached at 1b855a4
27nothing to commit, working directory clean
28 
29 
30➜  /Users/diguage/parent/child git:((1b855a4...)) git checkout master # 第三步
31 
32Switched to branch 'master'
33Your branch is up-to-date with 'origin/master'.

这种方式确实比上面简单多了,少了一条命令。(别笑!严肃点,哥是认真的!)

删除子模块

也许未来有一天,我们项目成功了,公司上市了,可以不再引用别人的代码,自己早轮子了,那么我们就可以把子模块从版本库中删除。D瓜哥原以为很麻烦,今天为了写文章,特意试了一下,其实很简单。(我艹,哥是不是暴露了什么?!)如下:

01➜  /Users/diguage/parent git:(master) git rm child
02 
03rm 'child'
04 
05 
06➜  /Users/diguage/parent git:(master) ✗ git status
07 
08On branch master
09Your branch is up-to-date with 'origin/master'.
10Changes to be committed:
11  (use "git reset HEAD <file>..." to unstage)
12 
13    modified:   .gitmodules
14    deleted:    child
15 
16 
17➜  /Users/diguage/parent git:(master) ✗ git commit -am "删除子模块"
18 
19[master b0b088b] 删除子模块
20 2 files changed, 4 deletions(-)
21 delete mode 160000 child
22 
23 
24➜  /Users/diguage/parent git:(master) git push origin master
25 
26Counting objects: 3, done.
27Delta compression using up to 8 threads.
28Compressing objects: 100% (2/2), done.
29Writing objects: 100% (3/3), 274 bytes | 0 bytes/s, done.
30Total 3 (delta 1), reused 0 (delta 0)
31To git@github.com:diguage/parent.git
32   5ac4dbb..b0b088b  master -> master

直接一条命令就搞定了: git rm <SubModuleName>

参考资料



作 者: D瓜哥,https://www.diguage.com/
原文链接:https://wordpress.diguage.com/archives/146.html
版权声明:非特殊声明均为本站原创作品,转载时请注明作者和原文链接。

分类: Linux, 挨踢(IT), 日拱一卒 标签: , ,
  1. 本文目前尚无任何评论.