24

如何设置 Git 项目以包含其他项目?

例如。我正在开发一个在线地图应用程序。我们开发了一个 GPS 工具和 SF 的一套装备。我们同时开发了一个 Python 地理映射脚本和一个不同的关注点(只关心地理映射)。我们自己的核心文件将两者结合起来,并在它们的基础上构建我们需要的应用程序。

每个项目都必须单独存在——对 GPS 感兴趣的人只对 GPS 感兴趣——但包含所有其他项目的“父”项目必须作为项目访问。

我花了一些时间试图理解子模块,但它们似乎对所需的东西有太多的独立性。

此外,如果可能的话,如果这些项目中的每一个都可以包含一个或两个重叠的脚本,那就太好了。一个 Git 项目是否可以包含一个不属于其“根”的文件,以便当任何一个团队更新该文件时,双方都可以受益?

这对 Git 可行吗?与水银?主机(GitHub、Gitorious)重要吗?

我有使用 Subversion 作为“父级”的想法——忽略 .git 文件夹,并将 Git 用于项目(忽略 .svn 文件夹)——但这只是最后的手段。

编辑:

解释为什么我不想要子模块:

  1. 用户下载时,zip 不包含子模块(此处此处)。当甚至合作者尝试设置项目时也是如此。这是一个表演终结者。
  2. 子模块被冻结 - 它们不会(轻松)获取所指向的项目的最新版本。
  3. 下面的精彩答案和NoPugs的独白中指出的其他原因。

子树合并(由 Paul 介绍给我,如下)不会:很难从合并到的项目中更新 [子树] 的源,并且该源必须位于“根”文件夹之外该项目。作为一个网络应用程序,我的所有页面都必须在内部链接到其中的一个文件夹,并且直接在该文件夹中完成测试和更新。(希望这对其他人来说清晰且有用。)

仍在研究建立“远程分支”,但仍然欢迎其他想法。

4

6 回答 6

15

我还没有发现子模块对我从事的(小)项目特别有用。设置它们后,处理整个项目需要为几乎每个命令添加额外的参数,并且语法并不完全规则。我想如果我从事具有更多子模块的大型项目,我会认为这是一个更有益的权衡。

有两种可能性可以将子项目保持为独立的 git 存储库,您可以将其拉入主(集成)存储库:

  • 使用子树合并 将您的外部项目放入 包含核心文件的主存储库中的单独子目录中。这使得从外部项目更新主项目变得容易,但将更改发送回外部项目很复杂。我认为这是包含项目依赖项的好方法,但它不适用于共享文件。 另一个简单的解释(链接固定)

  • 将每个项目设置为主存储库中的远程分支,并将每个项目合并到您的master(集成)分支中,该分支也包含您的核心文件。这需要一些纪律:如果您对主仓库中的外部项目进行任何更改,它们必须在分支中进行,然后合并到主库中;而且您永远不想合并到项目分支中。这使得将更改发送回外部项目变得很容易,并且是 Git 中完全可以接受的分支使用。

    您的共享脚本可以作为主目录中的另一个独立分支处理,您的外部合作伙伴可以从中提取和推送作为远程分支。

如果您尝试在同一目录中运行 SVN 和 Git,那么在任一系统中都很难使用分支,因为 SVN 通过复制文件目录进行分支,而 Git 跟踪指针。两个系统都不会自动看到您在另一个系统中创建的分支。我认为“解决方案”比它的价值更麻烦。

于 2009-04-06T18:16:49.430 回答
3

我使用 git 将我自己的 github 托管项目和我想使用的外部 UI 库拼接在一起。该库托管在 sourceforge 上的 subversion 存储库中。

我使用了 git-submodule 和 git-svn,它运行得相当好。缺点是:

  1. 为了跟上库存储库的最新状态,我必须执行新的提交来更新子模块 git hash “指针”。这是因为 git 子模块,不像 svn:externals,被固定到一个特定的提交 id。如果您真的想固定一个稳定版本,这可能不是真正的缺点,我正在使用 WIP 代码。

  2. 带有子模块的 git repo 的初始拉取需要使用“git submodule init”的额外步骤。这对您来说不是问题,但对于使用您的代码的其他人来说,他们必须记住或被告知在编译/运行/测试您的代码之前执行此步骤。

  3. 如果你使用命令行,很容易用 git-add 搞砸你的存储库。这是因为您键入git add subm<tab>要完成到git add submodule,但它会自动完成以git add submodule/- 注意尾部斜杠。如果您使用尾部斜杠执行命令,那么它会闪击子模块并添加其所有包含的文件。这可以通过使用 git-gui 来缓解,git add .或者只是训练自己删除斜线(它发生在我身上的次数足够多,我训练自己删除它)

  4. 子模块提交可能会弄乱 git rebase -i。我忘记了确切的细节,但如果你有一个“脏”的子模块并且你运行一个 rebase-interactive,那就特别糟糕了。通常使用脏树你不能变基,但不检查子模块。在一个变基组中有多个子模块提交也会导致问题。最后一个子模块哈希被提交给你列表中的第一个选择,这在以后修复是相当棘手的。这可以通过更仔细的工作流程来解决(即仔细决定何时进行子模块提交......)但可以是 PITA。

设置它的步骤大致如下:

  1. git svn clone https://project.svn.sourceforge.net/svnroot/project/project/trunk
  2. 将其作为“真正的”git 项目推送到例如 github
  3. 现在在您自己的 git 存储库中,运行git submodule init
  4. git submodule add git://github.com/project subproject
  5. 这次也将其推送到您自己的仓库中。

就是这样,或多或少。您将有一个新目录“子项目”,在您的情况下将是地理映射库。

每次您需要更新地理映射代码时,您将运行以下代码:

cd subproject
git svn rebase
git svn push  # this updates the git mirror of the subproject
cd ..
git add subproject # careful with the trailing slash!
git commit -m "update subproject"
git push # this pushes the commit that updates the subproject

我没有看过很多关于 git 子模块工作流程的教程,所以我希望这能帮助你做出决定。

于 2009-04-06T19:00:03.710 回答
1

git-submodule 可能是您正在寻找的:

http://book.git-scm.com/5_submodules.html

http://git-scm.org/gitwiki/GitSubmoduleTutorial

于 2009-04-06T10:09:07.043 回答
1

从我读过的关于Externals的一点点来看,它似乎是 SVN 'externals' 到 GIT 的一个端口。

这解决了 GIT 子模块的一些问题,包括自动更新到最新版本。

虽然我没有 SVN 外部或这个项目的经验,但对于某些人来说,这可能是比其他任何发布的更好的解决方案。

或者,以下软件(看起来可以与 GitHub 一起使用)。可能是另一种给猫剥皮的方法: 辫子软百科页面

于 2009-04-16T16:48:55.067 回答
0

这取决于您正在处理什么样的项目,以及需要哪些工具(如果有)与您的 SCM 交互。例如,Rails 经常使用 Capistrano 进行部署,Capistrano 对您的目录结构相对于存储库根目录的外观做出某些假设。在这种情况下,如果您有多个相互关联的 Rails 应用程序,则需要使用子模块。每个应用程序都有自己的存储库,然后您拥有一个更大的存储库,将每个独立的存储库作为子模块进行管理。

即使您没有做出此类假设的工具,良好的存储库设计也要求您将事情分解一下,如果有一天您可能想要独立使用更大项目的一个子部分,或者重用一些独立项目中的大量代码。

在 git 中很难在维护版本历史的同时提取存储库的某些子部分作为自己的独立实体,因此提前计划是一个好主意。

至于你的具体问题,老实说,我认为这是一个完美的例子,说明几个子模块是理想的。关于共享脚本,如果由于某种原因这实际上是一个被证明有问题的问题,您始终可以使用符号链接。

于 2009-04-16T16:52:44.310 回答
0

我按照https://github.com/jmnavarrol/simplest-git-subrepos(免责声明:我是它的作者)的轨迹,通过使它们相当独立来处理这些“外部”子组件。

实际上,我正在使用 Python 端口,因此我能够在 Bash 中添加困难的功能,例如 subrepos 配置文件是 YAML,例如:

---
# Subrepos' definition
#
# subrepos:
# - path: relative_path
#   repo: URL to git service
#   [gitref: gitref]

subrepos:
- path: 'projects/simplest-git-subrepos'
  repo: 'git@github.com:jmnavarrol/simplest-git-subrepos.git'
  gitref: 'v1.0.0'

这允许“修复”版本的分发以及简单的开发,无论是“主”“相关”项目。

于 2021-03-17T12:46:10.450 回答