问题描述
举例:我的工程叫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有更新,能否正常。
问题解答
回答1: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 的仓库中,所以最后才会无效的。
回答2:把一个仓库的里的子目录作为你的submodule这样的方式是不可以的。git submodule只支持整个仓库。
我发现很多依赖了submodule的xcode project都不会把submodule的project给去掉的。因为他们的是按照静态lib来依赖的,编译时会按照submodule的project先编译成lib.a文件,然后link到你的项目中。如果把submodule的project文件去掉,那么编译时,xcode会把submodule的source当做同一个项目来处理。先把*.m文件编译出来,然后再link。
楼上说得git-subtree.sh可能是个办法。不过我没尝试过。
最后还是建议你尝试cocoapods,嘿嘿。