We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在一个项目需要引入另一个项目时通常有两种方法:submodule or subtree,关于它们的特点和如何选择它们在 #21 中有说明就不赘述了,我们来看看如何使用submodule。
1. 初始化父项目my
开发人员A克隆父项目my到目录my-A
# git clone git@github.com:xhlwill/git-example-my.git my-A 正克隆到 'git-example-my'... warning: 您似乎克隆了一个空仓库。
然后新建一个文件a.txt,commit并推送到远程仓库。
# git commit -m "Initial commit" [master(根提交) 750bd31] Initial commit 1 file changed, 1 insertion(+) create mode 100644 a.txt # git push 枚举对象: 3, 完成. 对象计数中: 100% (3/3), 完成. 写入对象中: 100% (3/3), 226 bytes | 226.00 KiB/s, 完成. 总共 3 (差异 0),复用 0 (差异 0) To github.com:xhlwill/git-example-my.git * [new branch] master -> master
2. 初始化公共子模块项目sub
克隆子模块项目sub,并新建一个文件sub.txt,然后推送到远程。
# git clone git@github.com:xhlwill/git-example-sub.git 正克隆到 'git-example-sub'... warning: 您似乎克隆了一个空仓库。 # git commit -m "Initial" [master(根提交) f2e5348] Initial 1 file changed, 1 insertion(+) create mode 100644 sub.txt # git push origin 枚举对象: 3, 完成. 对象计数中: 100% (3/3), 完成. 写入对象中: 100% (3/3), 232 bytes | 232.00 KiB/s, 完成. 总共 3 (差异 0),复用 0 (差异 0) To github.com:xhlwill/git-example-sub.git * [new branch] master -> master
3. 为父项目添加子模块
开发人员 A 在父项目 my 中,把公共子项目 sub 添加到它的 libs 目录中
# git submodule add git@github.com:xhlwill/git-example-sub.git libs 正克隆到 '/Users/lovej/projects/github.com/xhlwill/git-example-my-A/libs'... remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 接收对象中: 100% (3/3), 完成. # cd libs # ls sub.txt # git status 位于分支 master 您的分支与上游分支 'origin/master' 一致。 要提交的变更: (使用 "git reset HEAD <文件>..." 以取消暂存) 新文件: .gitmodules 新文件: libs
添加后用 git status 查看发现多了子项目sub的文件夹和一个新文件.gitmodules
查看 .gitmodules 内容发现它记录了每个子模块的引用信息、在当前项目的位置、仓库地址
# cat .gitmodules [submodule "libs"] path = libs url = git@github.com:xhlwill/git-example-sub.git
然后别忘了把这些更改commit并推送到远程,这样my就是一个带有子模块项目(sub)的项目了
# git commit -m "add submodule" # git push
4. 其他成员克隆带有子模块的仓库
项目组其他成员如何 clone 该项目呢…… 假设开发人员 B 检出父项目到 my-B 目录,会发现在libs目录下并没有sub.txt文件,为什么呢?我们用 git submodule 查看子模块状态,会看到 submodule 状态的hash码和目录,注意前面有一个减号“-”,含义是子模块还没检出
# git clone git@github.com:xhlwill/git-example-my.git git-example-my-B 正克隆到 'git-example-my-B'... remote: Enumerating objects: 6, done. remote: Counting objects: 100% (6/6), done. remote: Compressing objects: 100% (4/4), done. remote: Total 6 (delta 0), reused 6 (delta 0), pack-reused 0 # git submodule -f2e5348513f60f212033722d72703ccc2344b8c6 libs
接着我们检出 submodule
# git submodule init 子模组 'libs'(git@github.com:xhlwill/git-example-sub.git)已对路径 'libs' 注册 # git submodule update 正克隆到 '/Users/lovej/projects/github.com/xhlwill/git-example-my-B/libs'... Submodule path 'libs': checked out 'f2e5348513f60f212033722d72703ccc2344b8c6'
这时候我们就能看到sub.txt文件了
5. 修改 Submodule
开发人员 B 要修改 submodule 的内容时(比如发现sub里某个组件有bug),进入到libs目录,修改前先看一下submodule的状态:
# git status 头指针分离于 f2e5348 无文件要提交,干净的工作区
为什么是 detached 状态呢?不应该在 master 分支吗? Git 对于 Submodule 有特殊的处理方式,在一个主项目中引入了 Submodule 其实 Git 做了3件事情:
A 在 my-A 中 push 之后其实就是更新了引用的 commit id,然后 B 在 clone 的时候获取到了 submodule 的 commit id,然后当执行 git submodule update 的时候 git 就根据 gitlink 获取submodule 的 commit id,最后获取 submodule 的文件,所以 clone 之后不在任何分支上;但是 master 分支的 commit id 和 HEAD 保持一致。
现在要修改子模块项目 sub 需要先切换到 master 分支,再提交修改:
# git checkout master # touch sub-2.txt # git commit -m "add sub-2 by B"
我们加了一个 sub-2.txt 文件,在主项目中修改 submodule 并推送到远程稍微繁琐一点,在 git push 之前我们先看看 my-B 的状态:
# git status 位于分支 master 您的分支与上游分支 'origin/master' 一致。 尚未暂存以备提交的变更: (使用 "git add <文件>..." 更新要提交的内容) (使用 "git checkout -- <文件>..." 丢弃工作区的改动) 修改: libs (新提交) 修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
libs 的状态表示有新的提交,这个比较特殊,git diff 看看 my-B 的状态会发现 libs 的 commit id 由 f2e5348513f60f212033722d72703ccc2344b8c6 变为 c70bc69f6f4479921fb8fca1552635a69c395ab4
现在回到 libs 目录,前面我们还没把子模块的更改推送到远程,先git push 把子模块 libs 目录的修改提交到仓库。
# git push
这仅仅完成了一步,还要在主项目 my-B 提交推送 (更改了引用子模块的 commit id):
# git add -u # git commit -m "update libs" # git push
好了,我们完成了子模块项目的修改并把主项目 libs 的最新 commit id 提交到了仓库。 接下来看看开发人员 A 在项目 my-A 中怎么获取新的 submodule 了。
6. 其他人员更新主项目
开发人员 A 进入 my-A 目录同步仓库:
# git pull remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Compressing objects: 100% (1/1), done. remote: Total 2 (delta 1), reused 2 (delta 1), pack-reused 0 展开对象中: 100% (2/2), 完成. 来自 github.com:xhlwill/git-example-my b64b53b..13fe210 master -> origin/master Fetching submodule libs 来自 github.com:xhlwill/git-example-sub f2e5348..c70bc69 master -> origin/master 更新 b64b53b..13fe210 Fast-forward libs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) # git status 位于分支 master 您的分支与上游分支 'origin/master' 一致。 尚未暂存以备提交的变更: (使用 "git add <文件>..." 更新要提交的内容) (使用 "git checkout -- <文件>..." 丢弃工作区的改动) 修改: libs (新提交)
pull 完之后会发现 libs 是 modified 的状态,但是并没有sub-2.txt 文件,这是为什么呢? 我们用 git diff 比较一下不同,从结果分析发现 submodule 的 commit id 更改了。 前面说了要在父项目更新 submodule 的内容首先要提交 submdoule 的内容,然后再更新父项目中引用的 submodule 的 commit id。现在我们看到的不同就是因为刚刚更改了 my-B 的submodule 的 commit id。 现在我们来更新 my-A 中的公共子模块
# git submodule update Submodule path 'libs': checked out 'c70bc69f6f4479921fb8fca1552635a69c395ab4'
现在再查看libs里子模块的文件内容,就已经更新到最新了。
7. 同步子模块的修改到主项目
sub项目通常为公用的模块,例如一套样式或一套images,风格改动后要同步到多个系统中,怎么办呢? 用 git submodule foreach 此命令循环进入每个子模块的目录,然后执行 foreach 后面的命令。 注:第一次用 git submodule foreach git pull 发现只会 fetch 下来但不会 merge……根据 git 的提示是因为当前子模块不在任何分支,用 git submodule foreach git pull origin master 就可以了。
git submodule foreach
# git submodule foreach git pull 进入 'libs' remote: Enumerating objects: 4, done. remote: Counting objects: 100% (4/4), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 展开对象中: 100% (3/3), 完成. 来自 github.com:xhlwill/git-example-sub c70bc69..b885e96 master -> origin/master 您当前不在一个分支上。 请指定您要合并哪一个分支。 详见 git-pull(1)。 git pull <远程> <分支> fatal: 对 libs 执行 run_command 返回非零值 # git submodule foreach git pull origin master 进入 'libs' 来自 github.com:xhlwill/git-example-sub * branch master -> FETCH_HEAD 更新 c70bc69..b885e96 Fast-forward sub-3.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 sub-3.txt
注意这时用git status查看libs是modified状态,记得把更改commit并推送到远程仓库
8. 新员工加入项目,一次性Clone项目及Submodules
一般人使用的时候都是使用如下命令:
# git clone git@github.com:xhlwill/git-example-my.git # git submodule init # git submodule update
上面的命令简直弱暴了,直接一行命令搞定:
# git clone --recursive git@github.com:xhlwill/git-example-my.git
The text was updated successfully, but these errors were encountered:
No branches or pull requests
在一个项目需要引入另一个项目时通常有两种方法:submodule or subtree,关于它们的特点和如何选择它们在 #21 中有说明就不赘述了,我们来看看如何使用submodule。
1. 初始化父项目my
开发人员A克隆父项目my到目录my-A
然后新建一个文件a.txt,commit并推送到远程仓库。
2. 初始化公共子模块项目sub
克隆子模块项目sub,并新建一个文件sub.txt,然后推送到远程。
3. 为父项目添加子模块
开发人员 A 在父项目 my 中,把公共子项目 sub 添加到它的 libs 目录中
添加后用 git status 查看发现多了子项目sub的文件夹和一个新文件.gitmodules
查看 .gitmodules 内容发现它记录了每个子模块的引用信息、在当前项目的位置、仓库地址
然后别忘了把这些更改commit并推送到远程,这样my就是一个带有子模块项目(sub)的项目了
4. 其他成员克隆带有子模块的仓库
项目组其他成员如何 clone 该项目呢……
假设开发人员 B 检出父项目到 my-B 目录,会发现在libs目录下并没有sub.txt文件,为什么呢?我们用 git submodule 查看子模块状态,会看到 submodule 状态的hash码和目录,注意前面有一个减号“-”,含义是子模块还没检出
接着我们检出 submodule
这时候我们就能看到sub.txt文件了
5. 修改 Submodule
开发人员 B 要修改 submodule 的内容时(比如发现sub里某个组件有bug),进入到libs目录,修改前先看一下submodule的状态:
# git status 头指针分离于 f2e5348 无文件要提交,干净的工作区
为什么是 detached 状态呢?不应该在 master 分支吗?
Git 对于 Submodule 有特殊的处理方式,在一个主项目中引入了 Submodule 其实 Git 做了3件事情:
A 在 my-A 中 push 之后其实就是更新了引用的 commit id,然后 B 在 clone 的时候获取到了 submodule 的 commit id,然后当执行 git submodule update 的时候 git 就根据 gitlink 获取submodule 的 commit id,最后获取 submodule 的文件,所以 clone 之后不在任何分支上;但是 master 分支的 commit id 和 HEAD 保持一致。
现在要修改子模块项目 sub 需要先切换到 master 分支,再提交修改:
我们加了一个 sub-2.txt 文件,在主项目中修改 submodule 并推送到远程稍微繁琐一点,在 git push 之前我们先看看 my-B 的状态:
libs 的状态表示有新的提交,这个比较特殊,git diff 看看 my-B 的状态会发现 libs 的 commit id 由 f2e5348513f60f212033722d72703ccc2344b8c6 变为 c70bc69f6f4479921fb8fca1552635a69c395ab4
现在回到 libs 目录,前面我们还没把子模块的更改推送到远程,先git push 把子模块 libs 目录的修改提交到仓库。
# git push
这仅仅完成了一步,还要在主项目 my-B 提交推送 (更改了引用子模块的 commit id):
好了,我们完成了子模块项目的修改并把主项目 libs 的最新 commit id 提交到了仓库。
接下来看看开发人员 A 在项目 my-A 中怎么获取新的 submodule 了。
6. 其他人员更新主项目
开发人员 A 进入 my-A 目录同步仓库:
pull 完之后会发现 libs 是 modified 的状态,但是并没有sub-2.txt 文件,这是为什么呢?
我们用 git diff 比较一下不同,从结果分析发现 submodule 的 commit id 更改了。
前面说了要在父项目更新 submodule 的内容首先要提交 submdoule 的内容,然后再更新父项目中引用的 submodule 的 commit id。现在我们看到的不同就是因为刚刚更改了 my-B 的submodule 的 commit id。
现在我们来更新 my-A 中的公共子模块
现在再查看libs里子模块的文件内容,就已经更新到最新了。
7. 同步子模块的修改到主项目
sub项目通常为公用的模块,例如一套样式或一套images,风格改动后要同步到多个系统中,怎么办呢?
用
git submodule foreach
此命令循环进入每个子模块的目录,然后执行 foreach 后面的命令。
注:第一次用 git submodule foreach git pull 发现只会 fetch 下来但不会 merge……根据 git 的提示是因为当前子模块不在任何分支,用 git submodule foreach git pull origin master 就可以了。
注意这时用git status查看libs是modified状态,记得把更改commit并推送到远程仓库
8. 新员工加入项目,一次性Clone项目及Submodules
一般人使用的时候都是使用如下命令:
上面的命令简直弱暴了,直接一行命令搞定:
# git clone --recursive git@github.com:xhlwill/git-example-my.git
The text was updated successfully, but these errors were encountered: