Git Submodule使用方法
假设有两个项目project1和project2代码仓库:
$ ls project1/
HEAD branches config description hooks info objects refs
$ ls project2/
HEAD branches config description hooks info objects refs
1. 从代码仓库clone开发库p1/p2
$git clone ../project1 p1
Cloning into 'p1'...
warning: You appear to have cloned an empty repository.
done.
$ git clone ../project2 p2
Cloning into 'p2'...
warning: You appear to have cloned an empty repository.
done.
2. 对p1/p2做一些改动并且push到原代码仓库
在p1中添加新文件file1并且push到远程库project1
$ touch file1
$ git add file1
$ git commit
[master (root-commit) 9132026] Init project 1 with file1
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file1
在p2中添加新文件file2并且push到远程库project2
$ touch file2
$ git add file2
$ git commit
[master (root-commit) 0e07357] Init project2 with file2
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 file2
3. 在开发库p1代码库中添加submodule ‘project2’
使用submodule add命令添加submodule到当前git代码库中,执行完成后submodule代码也会被clone到对应的目标目录。
git submodule add <URL to submodule remote> <submodule local dir>
例如:
$ git submodule add ../../project2 submodule/p2
此时代码已经被拉到本地submodule目录下,查看一下submodule目录已经同步好project2的代码:
$ ls
file1 submodule
$ ls submodule/p2/
file2
在project1目录中多出一个’.gitmodules’文件,该文件包含submodule信息:
$ cat .gitmodules
[submodule "submodule/p2"]
path = submodule/p2
url = /Users/wangq/tmp/submodule/project2
$ git submodule
0e0735740297cce3ef051c9c84d20d032d03311a submodule/p2 (heads/master)
这时候需要添加初始化一下这个submodule
git submodule init
git submodule update
初始化后在主代码库目录中可以查看到submodule相关的两个改动,这两个改动可以被commit。
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitmodules
new file: submodule/p2
$ git commit
[master 5d40507] Create submodule inside p1's working repository
2 files changed, 4 insertions(+)
create mode 100644 .gitmodules
create mode 160000 submodule/p2
4. 此时如果project2的开发人员更新了project2的代码,我们可以把最新的代码同步到submodule中
$ git pull
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /Users/wangq/tmp/submodule/project2
0e07357..db4f02b master -> origin/master
Updating 0e07357..db4f02b
Fast-forward
file2 | 1 +
1 file changed, 1 insertion(+)
查看一下其他人的改动内容如下:
$ cat file2
This line is change from another's working reposiroty
5.在p1中的submodule对project2进行了修改后也可以把新的修改发不到project2的远程库,这样project2的开发人员可以同步到最新的代码。
在p1的submodule目录中对p2进行修改并本地提交,然后把submodule的修改推到project2远程库中:
$ git push origin master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 335 bytes | 111.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /Users/wangq/tmp/submodule/project2
db4f02b..f600361 master -> master
这是project2的其他开发人员可以在自己的代码库中同步这部分修改内容:
$ git pull origin master
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /Users/wangq/tmp/submodule/test/../project2
* branch master -> FETCH_HEAD
db4f02b..f600361 master -> origin/master
Updating db4f02b..f600361
Fast-forward
file2 | 1 +
1 file changed, 1 insertion(+)
查看修改内容:
$ cat file2
This line is change from another's working reposiroty
This line is chaneg from p1's submodule repository <-- 这一行是p1开发人员增加的内容
使用中碰到的问题
Trap 1: “Server does not allow request for unadvertised object”
$ git submodule update --checkout
error: Server does not allow request for unadvertised object 55e720e9c4ca96ae1d1bde84a1db3a12c90b9700
Fetched in submodule path 'submodule/p2', but it did not contain 55e720e9c4ca96ae1d1bde84a1db3a12c90b9700. Direct fetching of that commit failed.
- 原因:
出现这个问题的原因是在submodule中进行的修改虽然已经commit到了superproject中,甚至是push到了superproject的远程库,但是当另外一个人尝试把这个superproject抓下来并同步这个submodule中的修改时,如果submodule的改动并未push到其对应的remote库,那么就会出现这个问题,因为update尝试从sudmobule的远程库pull对应的改动(55e720e9c4ca96ae1d1bde84a1db3a12c90b9700),而这个改动并未被push到远程库,因此也就不存在。