Pending
基于公司的项目会越来越多,常常需要提取一个公共的类库提供给多个项目使用,但是这个library怎么和git在一起方便管理呢?
我们需要解决下面几个问题:
- 如何在git项目中导入library库?
answer:git submodule add【library-url】,参考【使用submodule】。
- library库在其他的项目中被修改了可以更新到远程的代码库中?
answer:可以,需要在submodule目录更新提交,在业务架构中建议单人操作更新提交,实现读写剥离
- 其他项目如何获取到library库最新的提交?
answer:【使用submodule】中有说明每个submodule中有独立的commit id,依赖commit id单独管理submodule目录,依据submodule目录中commit id是否与公共库的同步选择是否更新
- 如何在clone的时候能够自动导入library库?
answer:参考【Clone Submodule】,此处建议方法二
解决以上问题,可以考虑使用git的 Submodule来解决。
git Submodule 是一个很好的多项目使用共同类库的工具,他允许类库项目做为repository,子项目做为一个单独的git项目存在父项目中,子项目可以有自己的独立的commit,push,pull。而父项目以Submodule的形式包含子项目,父项目可以指定子项目header,父项目中会的提交信息包含Submodule的信息,再clone父项目的时候可以把Submodule初始化。
- 使用git命令直接添加Submodule:
git submodule add git@github.com:damonnie/redlock-php.git redlock(别名)
- 使用git status命令查看当前仓库状态:
可以看到多了两个需要提交的文件:.gitmodules和 redlock
- .gitmodules 内容包含Submodule的主要信息,指定reposirory,指定路径:
- 要查看当前代码仓库所使用的子模块及其状态,除了看 .gitmodules 文件外,还可以执行 git submodule命令
- 新文件redlock保存子模块的信息,默认情况下子模块会将子项目放到一个与仓库同名的目录中,本例中是redlock。如果想放到其他地方,那么可以命令后添加一个不同的路径。此处,可以添加多个不同的子模块
这里需要说明的是,submodule目录只保护子项目的commit id,父项目的git并不会记录submodule的文件变动。另外,这两个文件都需要提交到父项目的git中
- 需要确认有对Submodule的commit权限:
cd redlock
- 修改其中的一个文件,git status查看变动:
modified: README.md
- 提交更改内容,并push远程
git commit -m “test submodule”&& git push
- 此处redlock中已经变更为submodule最新的commit id.由原来的4066b307978ac81bf16e878aeb21210a5b794f06变更为717af34cae93e0d24dba04bbc166b8f1840f3893
更新Submodule有两种方式:
- 在父项目的目录下直接运行
git submodule foreach git pull
- 在Submodule的目录下面更新(推荐此操作)
cd redlock && git checkout (所要同步的commit id所在分支) && git pull
可以看到在Submodule的目录中,使用git和单独的一个项目是一样的,注意更新Submodule的时候如果有新的commit id产生,需要在父项目产生一个新的提交,git-Submodule文件中的 Submodule commit会变为最新的commit id。
clone Submodule有两种方式 一种是采用递归的方式clone整个项目,一种是clone父项目,再更新子项目
- 采用递归参数--recursive
git clone git@github.com:DamonNie/git-Submodule.git --recursive
这里一定要带上递归参数,否则init Submodule 的clone是不全的
- 第二种方法先clone父项目,再初始化Submodule
git clone git@github.com:damonnie/git-Submodule.git && cd git-Submodule
- 初始化submodule:
git submodule init
- 更新Submodule:
git submodule update
此处要注意:submodule文件都是init状态,如要获取最新,请切换要同步的commit id所在分支,并git pull操作
git 并不支持直接删除Submodule需要手动删除对应的文件
- 使用vim .git/config 可打开vim编辑,删除对应的内容
- 使用rm -rf .git/modules/redlock, 删除.git下的缓存模块,最后提交项目。
- 使用git rm --cached redlock将redlock从版本控制中删除(本地仍保留有),若不需要可不带 --cached进行完全删除
- 使用vim .gitmodules 可打开vim编辑,删除对应的内容
字面意思上理解就是,有git工具没有跟踪到的文件切换后会被覆盖。通过资料查询解决方法
**解决办法:删除这些文件,再切换到对的分支上再拉取代码**
git clean -d -fx ""
如若依然无法切换,删除git submodule对应控制的代码即可。
- 使用git diff时候提示我:
diff --git a/fin-common-ultimate b/fin-common-ultimate
--- a/fin-common-ultimate
+++ b/fin-common-ultimate
@@ -1 +1 @@
-Subproject commit 0fdda668c6480ecb21eae7c6a8cd1357ff531d4b
+Subproject commit 0fdda668c6480ecb21eae7c6a8cd1357ff531d4b-dirty
答:在git的1.7.0及更高版本中,如果子模块具有任何已修改的文件或未跟踪的文件,则它们被视为脏文件,而以前,只有子模块中的HEAD指向错误的提交时,情况才会如此。 解决方案:
1、在返回父模块之前,提交或撤销子模块中的修改文件。可以使用一下命令撤销更改:
git submodule foreach --recursive git checkout .
2、忽略"脏"的子模块
# 执行git命令:
git status --ignore-submodules=dirty
#忽略任何子模块中的所有未跟踪文件
git config --global diff.ignoreSubmodules dirty
# 添加--ignore-submodules到中git diff
[diff]
ignoreSubmodules = dirty
这里我们使用第一种方案,撤销脏的子模块中的修改文件。更多详细请移步Git diff says subproject is dirty
参考: 姜家志:使用Git Submodule管理子模块唐巧的博客:Git submodule的坑