Git Submodule完整教程(3/3)

2.8.1 牛刀小试

?
1
2
3
4
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ grep path .gitmodules | awk '{ print $3 }' > /tmp/study-git-submodule-dirs
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ cat /tmp/study-git-submodule-dirs
  libs /lib1
  libs /lib2

我们通过分析.gitmodules文件得出子模块的路径,然后就可以根据这些路径进行更新。

2.8.2 上路

?
1
2
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ mkdir bin
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ vi bin /update-submodules .sh

把下面的脚本复制到bin/update-submodules.sh中:

?
1
2
3
4
5
6
7
8
9
#!/bin/bash
grep path .gitmodules | awk '{ print $3 }' > /tmp/study-git-submodule-dirs
 
# read
while read LINE
do
     echo $LINE
     ( cd ./$LINE && git checkout master && git pull)
done < /tmp/study-git-submodule-dirs

稍微解释一下上面的脚本执行过程:

  • 首先把子模块的路径写入到文件/tmp/study-git-submodule-dirs中;

  • 然后读取文件中的子模块路径,依次切换到master分支(修改都是在master分支上进行的),最后更新最近改动。

2.8.3 2013-01-19更新

网友@紫煌给出了更好的办法,一个命令就可以代替上面的bin/update-submodules.sh的功能:

?
1
git submodule foreach git pull

此命令也脚本一样,循环进入(enter)每个子模块的目录,然后执行foreach后面的命令。

该后面的命令可以任意的,例如 git submodule foreach ls -l 可以列出每个子模块的文件列表

2.8.3 体验工具带来的便利

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ git submodule
+36ad12d40d8a41a4a88a64add27bd57cf56c9de2 libs /lib1 (heads /master )
+7290dce0062bd77df1d83b27dd3fa3f25a836b54 libs /lib2 (heads /master )
 
# 添加执行权限
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ chmod +x . /bin/update-submodules .sh
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ . /bin/update-submodules .sh
libs /lib1
Already on 'master'
remote: Counting objects: 4, done .
remote: Compressing objects: 100% (2 /2 ), done .
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3 /3 ), done .
From /home/henryyan/submd/repos/lib1
    36ad12d..8c666d8  master     -> origin /master
Updating 36ad12d..8c666d8
Fast-forward
  README |    1 +
  1 files changed, 1 insertions(+), 0 deletions(-)
  create mode 100644 README
libs /lib2
Switched to branch 'master'
remote: Counting objects: 5, done .
remote: Compressing objects: 100% (2 /2 ), done .
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3 /3 ), done .
From /home/henryyan/submd/repos/lib2
    7290dce..e372b21  master     -> origin /master
Updating 7290dce..e372b21
Fast-forward
  lib2-features |    1 +
  1 files changed, 1 insertions(+), 0 deletions(-)
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ git submodule
  8c666d86531513dd1aebdf235f142adbac72c035 libs /lib1 (heads /master )
  e372b21dffa611802c282278ec916b5418acebc2 libs /lib2 (heads /master )
 
  ➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ git status
# On branch master
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#   bin/
nothing added to commit but untracked files present (use "git add" to track)
< /file >

更新之后的两个变化:

  • git submodule的结果和project2的submodule commit id保持一致;

  • project1-b不再提示new commits了。

现在可以把工具添加到仓库了,当然你可以很骄傲的分享给其他项目组的同事。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ git add bin /update-submodules .sh
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) ✗ git commit -m "添加自动更新submodule的快捷脚本^_^"
[master 756e788] 添加自动更新submodule的快捷脚本^_^
  1 files changed, 9 insertions(+), 0 deletions(-)
  create mode 100755 bin /update-submodules .sh
➜ henryyan@hy-hp  ~ /submd/ws/project1-b git:(master) git push
Counting objects: 5, done .
Delta compression using up to 2 threads.
Compressing objects: 100% (3 /3 ), done .
Writing objects: 100% (4 /4 ), 625 bytes, done .
Total 4 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (4 /4 ), done .
To /home/henryyan/submd/ws/ .. /repos/project1 .git
    8fcca50..756e788  master -> master

2.9 新进员工加入团队,一次性Clone项目和Submodules

一般人使用的时候都是使用如下命令:

?
1
2
3
git clone /path/to/repos/foo .git
git submodule init
git submodule update
新员工不耐烦了,嘴上不说但是心里想:怎么那么麻烦?

上面的命令简直弱暴了,直接一行命令搞定:

?
1
git clone --recursive /path/to/repos/foo .git

recursive参数的含义:可以在clone项目时同时clone关联的submodules。

git help 对其解释:

--recursive, --recurse-submodules
   After the clone is created, initialize all submodules within, using their default settings. This is equivalent to running git
   submodule update --init --recursive immediately after the clone is finished. This option is ignored if the cloned repository
   does not have a worktree/checkout (i.e. if any of --no-checkout/-n, --bare, or --mirror is given)

2.9.1 使用一键方式克隆project2

?
1
2
3
4
5
6
7
8
9
10
11
➜ henryyan@hy-hp  ~ /submd/ws  git clone --recursive .. /repos/project2 .git project2-auto-clone-submodules
Cloning into project2-auto-clone-submodules...
done .
Submodule 'libs/lib1' ( /home/henryyan/submd/repos/lib1 .git) registered for path 'libs/lib1'
Submodule 'libs/lib2' ( /home/henryyan/submd/repos/lib2 .git) registered for path 'libs/lib2'
Cloning into libs /lib1 ...
done .
Submodule path 'libs/lib1' : checked out '8c666d86531513dd1aebdf235f142adbac72c035'
Cloning into libs /lib2 ...
done .
Submodule path 'libs/lib2' : checked out 'e372b21dffa611802c282278ec916b5418acebc2'

舒服……

3.移除Submodule

牢骚:搞不明白为什么git不设计一个类似:git submodule remove的命令呢?

我们从project1.git克隆一个项目用来练习移除submodule:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
➜ henryyan@hy-hp  ~ /submd/ws  git clone --recursive .. /repos/project1 .git project1-remove-submodules
Cloning into project1-remove-submodules...
done .
Submodule 'libs/lib1' ( /home/henryyan/submd/repos/lib1 .git) registered for path 'libs/lib1'
Submodule 'libs/lib2' ( /home/henryyan/submd/repos/lib2 .git) registered for path 'libs/lib2'
Cloning into libs /lib1 ...
done .
Submodule path 'libs/lib1' : checked out '8c666d86531513dd1aebdf235f142adbac72c035'
Cloning into libs /lib2 ...
done .
Submodule path 'libs/lib2' : checked out 'e372b21dffa611802c282278ec916b5418acebc2'
➜ henryyan@hy-hp  ~ /submd/ws  cd !$
➜ henryyan@hy-hp  ~ /submd/ws  cd project1-remove-submodules

3.1 Step by

1、删除git cache和物理文件夹

?
1
2
3
4
➜ henryyan@hy-hp  ~ /submd/ws/project1-remove-submodules git:(master) git rm -r --cached libs/
rm 'libs/lib1'
rm 'libs/lib2'
➜ henryyan@hy-hp  ~ /submd/ws/project1-remove-submodules git:(master) ✗ rm -rf libs

2、删除.gitmodules的内容(或者整个文件) 因为本例只有两个子模块,直接删除文件:

?
1
➜ henryyan@hy-hp  ~ /submd/ws/project1-remove-submodules git:(master) ✗ rm .gitmodules
如果仅仅删除某一个submodule那么打开.gitmodules文件编辑,删除对应submodule配置即可。

3、删除.git/config的submodule配置 源文件:

[core]
    repositoryformatversion = 0 
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = /home/henryyan/submd/ws/../repos/project1.git
[branch "master"]
    remote = origin
    merge = refs/heads/master
[submodule "libs/lib1"]
    url = /home/henryyan/submd/repos/lib1.git
[submodule "libs/lib2"]
    url = /home/henryyan/submd/repos/lib2.git

删除后:

[core]
    repositoryformatversion = 0 
    filemode = true
    bare = false
    logallrefupdates = true
[remote "origin"]
    fetch = +refs/heads/*:refs/remotes/origin/*
    url = /home/henryyan/submd/ws/../repos/project1.git
[branch "master"]
    remote = origin
    merge = refs/heads/master

4、提交更改

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
➜ henryyan@hy-hp  ~ /submd/ws/project1-remove-submodules git:(master) ✗ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#   deleted:    libs/lib1
#   deleted:    libs/lib2
#
# Changes not staged for commit:
#   (use "git add/rm ..." to update what will be committed)
#   (use "git checkout -- ..." to discard changes in working directory)
#
#   deleted:    .gitmodules
#
➜ henryyan@hy-hp  ~ /submd/ws/project1-remove-submodules git:(master) ✗ git add .gitmodules
➜ henryyan@hy-hp  ~ /submd/ws/project1-remove-submodules git:(master) ✗ git commit -m "删除子模块lib1和lib2"
[master 5e2ee71] 删除子模块lib1和lib2
  3 files changed, 0 insertions(+), 8 deletions(-)
  delete mode 100644 .gitmodules
  delete mode 160000 libs /lib1
  delete mode 160000 libs /lib2
➜ henryyan@hy-hp  ~ /submd/ws/project1-remove-submodules git:(master) git push
Counting objects: 3, done .
Delta compression using up to 2 threads.
Compressing objects: 100% (2 /2 ), done .
Writing objects: 100% (2 /2 ), 302 bytes, done .
Total 2 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (2 /2 ), done .
To /home/henryyan/submd/ws/ .. /repos/project1 .git
    756e788..5e2ee71  master -> master
< /file >< /file >< /file >

4.结束语

对于Git Submodule来说在刚刚接触的时候多少会有点凌乱的赶紧,尤其是没有接触过svn:externals

本文从开始创建项目到使用git submodule的每个步骤以及细节、原理逐一讲解,希望到此读者能驾驭它。

学会了Git submdoule你的项目中再也不会出现大量重复的资源文件、公共类库,更不会出现多个版本,甚至一个客户的多个项目风格存在各种差异。

本文的写作来源于工作中的实践,如果您对于某个做法有更好的办法还请赐教,希望能留下您宝贵的意见。

原创文章,转载请注明出处! Git Submoudle使用完整教程--咖啡兔

你可能感兴趣的:(其他)