使用Git的项目中的项目

时间:2009-04-06 08:54:48

标签: git version-control git-submodules

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

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

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

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

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

这对Git有用吗? Mercurial?主持人(GitHub,Gitorious)是否重要?

我有使用Subversion作为'父'的想法 - 忽略.git文件夹,并使用Gi​​t作为项目(忽略.svn文件夹) - 但这只是最后的手段。

编辑:

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

  1. 当用户下载时,zip不包含子模块(here& here)。 甚至当合作者试图设置项目时也是如此。这是一个表演塞。
  2. 子模块被冻结 - 它们(不容易)获取正在指向的项目的最新版本。
  3. 下面和monologue at NoPugs中的精彩答案中指出的其他原因。
  4. 子树合并(由Paul在下面介绍)不会这样做:很难从合并到的项目中更新[子树]的源,并且该源必须位于'root之外'项目文件夹。作为一个Web应用程序,所有页面内部链接到其中的文件夹至关重要,并且测试和更新将直接在该文件夹中完成。 (希望这对其他人来说是明确和有用的。)

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

6 个答案:

答案 0 :(得分:13)

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

有两种可能性可以将子项目作为独立的git repos保存到主(集成)仓库中:

  • 在主仓库中使用包含核心文件的子树合并 to bring your external projects into separate subdirectories。这使得从外部项目更新主项目变得容易,但是将更改发送回外部项目很复杂。我认为这是一种包含项目依赖关系的好方法,但它对共享文件效果不佳。 Another simple explanation (link fixed)

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

    您的共享脚本可以作为主目录中的另一个独立分支处理,外部合作伙伴可以将其作为远程分支进行处理。

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

答案 1 :(得分:3)

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

我使用了git-submodule和git-svn,效果相当不错。缺点是:

  1. 为了跟上库存储库的最新状态,我不得不执行一个新的提交来更新子模块git hash“pointer”。这是因为与svn:externals不同,git子模块被固定到特定的提交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,那就特别糟糕了。通常使用脏树,您不能重新绑定,但不检查子模块。在rebase组中有几个子模块提交也会导致问题。最后一个子模块哈希被提交到列表中的第一个选择,这在以后修复是非常棘手的。这可以通过更仔细的工作流程来解决(即仔细决定何时进行子模块提交......)但可以是PITA。

  5. 设置此步骤的步骤如下:

    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. 这次也把它推出你自己的回购。
    6. 就是这样,或多或少。您将拥有一个新目录“子项目”,在您的情况下将是地理映射库。

      每次需要更新地理映射代码时,都会运行类似:

      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子模块工作流程的教程,所以我希望这有助于你做出决定。

答案 2 :(得分:1)

答案 3 :(得分:1)

从我读到的关于Externals的一点点开始,它似乎是一个SVN'外部'到GIT的端口。

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

虽然我没有SVN外部或该项目的经验,但对于某些人而言,它可能比其他任何人发布的更好。

或者,以下软件(看起来它可以与GitHub一起使用)。可能是一些皮肤猫的另一种方式: BraidSoftpedia page

答案 4 :(得分:0)

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

即使你没有做出这些假设的工具,好的存储库设计也要求你稍微分解一下,如果有一天你可能想要独立使用一个更大的项目的子部分的可能性最小的话,或在某个独立项目中重用一些大量代码。

在git中保存版本历史记录时,将存储库的某个子部分作为自己的独立实体提取出来很困难,因此提前计划是个好主意。

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

答案 5 :(得分:0)

我使用那些“外部” 子组件,使它们相当独立,遵循 https://github.com/jmnavarrol/simplest-git-subrepos 的轨迹(免责声明:我是它的作者)。

实际上,我正在使用 Python 端口,因此我能够在 Bash 中添加困难的功能,例如子存储库配置文件是 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'

这允许 “修复” 版本的分发以及简单的开发,包括 “master”“related” 项目。