举例:我的工程叫My,目录树如下
My |-- My | |-- Support | |-- main.m | |-- images | |-- My-Prefix.pch | |-- My-Info.plist | |-- MyAppDelegate.h | |-- MyAppDelegate.m | |-- My.xcodeproj
我希望把项目AFNetworking加成Submodule,他的目录树如下
AFNetworking |-- AFNetworking // 这个是真正需要的目录 |-- AFNetworking.xcworkspace |-- Example |-- .gitignore |-- AFNetworking.podspec |-- CHANGES |-- LICENSE |-- README.md
我要把AFNetworking加成submodule
git submodule add https://github.com/AFNetworking/AFNetworking.git My/Support/AFNetworking
最终My的目录结构
My |-- My | |-- Support | | |-- AFNetworking | | |-- AFNetworking // 这个是真正需要的目录 | | |-- AFNetworking.xcworkspace | | |-- Example | | |-- .gitignore | | |-- AFNetworking.podspec | | |-- CHANGES | | |-- LICENSE | | |-- README.md | | | |-- main.m | |-- images | |-- My-Prefix.pch | |-- My-Info.plist | |-- MyAppDelegate.h | |-- MyAppDelegate.m | |-- My.xcodeproj
我希望得到的目录结构是
My |-- My | |-- Support | | |-- AFNetworking // 这个是真正需要的目录 | | | |-- main.m | |-- images | |-- My-Prefix.pch | |-- My-Info.plist | |-- MyAppDelegate.h | |-- MyAppDelegate.m | |-- My.xcodeproj
我通过在子模块目录执行这个命令,达到了效果
git filter-branch -f --subdirectory-filter AFNetworking/AFNetworking -- --all
然后
git filter-branch -f --index-filter "git rm -r -f --cached --ignore-unmatch AFNetworking/AFNetworking" --prune-empty
然后回到父仓库commit并push
看起来一切完美了,但是我重新在clone的时候
这个Submodule的状态是挂的。。。完全clone不出来,AFNetworking只是个目录,没有文件内容
我用SourceTree打开这个工程,然后看通过submodule的方式打开AFNetworking,reset一下,目录结构就回到运行 filter-branch 命令之前的样子了
也就是说,这个效果只有我一个人在运行了 filter-branch 之后看的到,有没有什么办法,可以让大家都看到呢?
另外,我还不知道这样做了以后,如果submodule有更新,能否正常。
git 的 submodule 方式不会向仓库添加实际的的内容的,只会通过 .gitmodules 文件保留相应的子模块的哈希值。
由于你要真正要用的代码处于一个子目录中,我的方案是你先把这个子目录提取成一个单独的仓库(可以使用 git-subtree.sh 这个脚本),然后再添加这个仓库为 submodule(或者直接使用 git-subtree.sh 把实际的代码集成到你的项目,这样别人克隆就不需要更新 submodule 了)。这样做的缺点就是每当上游有更新,就需要对 submodule 的仓库做相应更新。
另外:git-subtree.sh 已经合并入 git 了,可能并不在 PATH 中,不能直接执行,不过应该在 git 的安装中的。
另一个思路:
建立 bundles 目录,添加原仓库为 submodule 到此,然后对需要的子目录做相对路径软链接,git 能够正确处理软链接。这可能是比较好的一个办法了,不需要额外维护同上游的同步。
-----------
你在子模块目录中进行的
subdirectory-filter
已经是 git-subree.sh 的 split 操作了,这个时候该仓库已经和 orgin 完全不同了,等于重新建立了以该 subdirectory 为根的一个仓库,这个仓库中的对象只在你的本地,并不包含在 origin 的仓库中,所以最后才会无效的。