为什么要使用 Git 子树
优点
- 受旧版 Git 支持(甚至比 v1.5.2 更旧)。
- 简单的工作流管理。
- 超级项目完成后可用的子项目代码。
- 使用 git subtree 不需要 Git 新知识。
- 未添加新的元数据文件(例如,.gitmodule)。
- 无需依赖项的单独存储库副本即可修改内容。
缺点
- 了解新的合并策略。
- 为子项目向上游提供复杂的贡献代码。
- 不要混合超级和子项目代码。
正如我们在上一页中提到的,Git Submodule 仅在某些情况下有用。
但是有一个更好的方法来跟踪软件依赖的历史。
许多开发人员更喜欢 Git Subtree 而不是 Git Submodule。
如何使用 Git 子树
假设有一个外部项目,并且我们想将其添加到存储库中。
例如,要在存储 vim 设置的存储库中添加 vim 扩展,请执行以下操作:
git subtree add --prefix .vim/bundle/example https://github.com/Example/vim-example.git master --squash
这会将 vim-fireplace 项目的整个历史压缩到文件夹 .vim/bundle/fireplace 中,记录当时 master 的 SHA-1 以供将来参考。
输出是以下两个提交:
commit 6d7054b3gcea64e2e31f4d6fb2e3be12e5865e87 Merge: 87fa91e ef86deb Author: Ann Smith<ann@smith.com> Date: Tue Jun 10 13:37:03 2014 +0200 Merge commit 'fe67ddf158faccff4082d78a25c45d8cd93e8ba8' as '.vim/bundle/example' commit fe67ddf158faccff4082d78a25c45d8cd93e8ba8 Author: Ann Smith<ann@smith.com> Date: Tue Jan 12 13:37:03 2014 +0200 Squashed '.vim/bundle/example/' content from commit b999b09 git-subtree-dir: .vim/bundle/example git-subtree-split: b999b09cd9d69f359fa5668e81b09dcfde455cca
要将子文件夹更新到子存储库的最新版本,请运行以下命令:
git subtree pull --prefix .vim/bundle/example https://github.com/Exampel/vim-example.git master --squash
但是, git subtree 存储子项目提交 ID 而不是元数据中的引用。
查找与提交相关的符号名称:
git ls-remote https://github.com/Example/vim-example.git | grep <sha-1>
添加子项目作为远程
添加为遥控器可缩短此过程:
git remote add -f vim-double-upon https:/hostname.org/example/vim-plugins.git
添加子树:
git subtree add --prefix .vim/bundle/vim-double-upon vim-double-upon master --squash
像这样更新子项目:
git fetch vim-double-upon master git subtree pull --prefix .vim/bundle/vim-double-upon vim-double-upon master --squash
Git subtree 是子模块的替代方案,但如果子模块旨在将另一个项目放在存储库目录中并保持远程存储库同步,则 git subtree 允许将子项目分开并允许主存储库和子项目之间的双向协作。
什么是 Git 子树
Git Subtree 是 Git Submodule 的替代品。
它允许将一个存储库作为子目录嵌套在另一个存储库中。
它是跟踪软件依赖关系历史的方法之一。
但是子树不应该与子模块混淆。
与子模块不同,子树不需要存储库中的 .gitmodules 文件或者 gitlinks。
子树只是一个可以与项目一起提交、分支和合并的子目录。
在没有远程跟踪的情况下使用 Git 子树
在指定的前缀文件夹中添加 git 子树。
使用 --squash 标志在主存储库中保留整个子项目历史记录:
git subtree add --prefix .vim/bundle/vim-double-upon https:/hostname.org/example/vim-plugins.git master --squash
结果如下:
git fetch https:/hostname.org/example/vim-plugins.git master warning: no common commits remote: Counting objects: 325, done. remote: Compressing objects: 100% (145/145), done. remote: Total 325 (delta 101), reused 313 (delta 89) Receiving objects: 100% (325/325), 61.47 KiB, done. Resolving deltas: 100% (110/110), done. From https:/hostname.org/vim-plugins.git * branch master -} FETCH_HEAD Added dir '.vim/bundle/vim-double-upon '
这通过将 vim-surround 存储库的整个历史记录压缩为一个来创建合并提交:
3bca0ad [4 minutes ago] (HEAD, stree) Merge commit 'fa2f5dc4f1b94356bca8a440c786a94f75dc0a45' as '.vim/bundle/vim-double-upon' [John Brown] fa2f5dc [4 minutes ago] Squashed '.vim/bundle/vim-double-upon/' content from commit 13189ec [John Brown]
要从上游存储库更新插件的代码,请执行 git subtree pull:
git subtree pull --prefix .vim/bundle/vim-double-upon https:/hostname.org/example/vim-plugins.git master --squash
要使命令更短,请将子项目添加为远程。
在 Git 子树之后rebase
其中我们应该使用 git rebase 的 --interactive 模式并删除添加提交,然后执行 rebase--continue 并在 rebase 过程完成后重新执行 git subtree add 命令。
选项
-q, --quiet | 在stderr上抑制不必要的结果消息。 |
-d, --debug | 在STDERR中产生更多不必要的结果消息。 |
-P <prefix>, --prefix=<prefix> | 将存储库中的路径定义为要操作的子树。所有命令都是强制性的。 |
-m <message>, --message=<message> | 指定%26lt;消息%26gt;作为合并提交的提交消息。它仅适用于添加,合并和拉动。 |