【问题标题】:git multiple repository managementgit 多仓库管理
【发布时间】:2012-09-23 21:55:40
【问题描述】:

我正在做一个项目,我们用 git 管理外部库/头文件和 qa。以下是每个开发人员的目录结构:

~/dev/proj 
~/dev/ext 
~/dev/qa

proj、ext 和 qa 是 不同的 git 存储库。在 svn 下,这些目录的同步很简单:在 ~/dev 下的单个更新将递归地更新所有这些目录。使用 git,我们需要为每个目录分别执行“git pull”。这不好;有人总是会忘记更新(git pull)这些目录之一,他的项目将不同步(例如,新的 qa 不会与旧代码一起通过)。我查看了“git submodules”,它没有为“git pull”提供一个点来同时更新这三个单独的模块[更正:我在这里错了,但请阅读我的答案below]

您可能会争辩说我们应该将 proj、ext 和 qa 放在同一个 git 存储库下,但我认为这违反了 git 将不同概念保存在不同存储库中的理念。

对于这个琐碎的问题,有没有人有解决方案(除了编写脚本对 ~/dev 下的每个目录执行 git pull )?

谢谢,

阿尔坦

【问题讨论】:

    标签: git project-management git-svn


    【解决方案1】:

    我的理念是:如果我总是需要将 X 和 Y 放在一起,那么从逻辑上讲,它们属于同一个存储库。仅当存在适当的隔离时,使用子模块才有意义 - 想想外部供应商库,您不希望随意引入更新并且您不希望您的团队能够直接编辑它们 - 这是有道理的。但是,无论您如何切片,它都会增加步骤。我坚持“如果它是一个项目,就把它放在一个存储库中”,不管我在理论上如何将它分解成更“像 git”。

    【讨论】:

    • ext 是外部库,可以与其他项目共享。还有一种情况是,人们可能想要在没有代码的情况下签出 qa [使用某个发布代码运行 qa]。因此,将它们分开存放是有好处的。
    • 我没有否认这些好处。我根本不认为这种设置的好处超过了现实
    【解决方案2】:

    博士先生,

    您正在将苹果与橙子进行比较。 git-submodules 类似于svn:externals,又名 svn-submodules。事实上,当您使用-r 在特定版本附加一个 svn 子模块时,行为几乎相同。要使用 svn-submodules 提交,您必须分别在每个子模块目录中提交,就像使用 git-submodules 一样。

    但是有一个很大的不同:大多数开发者,至少在开发的某个阶段,更喜欢附加到每个子模块的 分支,这是 git-submodules 不支持的。这对协调发展很有用。 (Google 的 Repo 工具是一个围绕 Git 的包装器,用于与代码审查工具 Gerrit 一起使用,有点类似。但请相信我:远离 Repo。它解决了一个不同的问题。)最大的缺点是您无法恢复代码库的精确轮廓。这在一段时间内似乎还不错,但我听说过令人讨厌的战争故事。

    您的替代方案不是 Subversion,而只是一个单一的存储库,可以在 GitSubversion 或其他任何地方。但是您实际上想要单个回购和多个回购的组合,对吗?你想要每个人的好处。所以你需要一个更复杂的解决方案。

    一个想法是拥有一个项目存储库,您可以在其中进行大部分开发工作,另外还有几个单独的存储库,您可以从中分发模块:

    proj/.git
    proj/subA
    proj/subB
    subA/.git
    subB/.git
    

    您可以使用 rsync 在它们之间移动代码。美妙之处在于您在开发和分发之间做出了明显的区分。您可以正常开发大型项目,包括分支、合并等。当您准备将子目录作为库分发时,您可以准确确定所需的库版本,并将其复制到自己的存储库中。当您需要合并而不只是复制时,有git subtree merge strategy

    还有另一个系统,建立在子树合并策略之上。它被称为git-subtrees,它是 git-1.7.11 的一部分。 Here 很好地描述了它的操作。您可以从图片中看到它的时间线看起来很混乱,但从功能上讲,它正是您想要的。 Here 是最近的一篇文章,提供了很好的建议。

    如果您不介意 git-submodules 的额外“更新”步骤,但您对它如何处理冲突感到不安,您可以尝试giternal。作者包含了一个脚本来展示其行为与 git-submodules 和 braid(用于出售子模块,但不合并它们)的比较。

    就个人而言,我喜欢git-slave,它是一个简单的 git 包装器。基本上,它将您的gits 命令作为git 命令应用于您的所有存储库。这真的只是一种方便。它非常容易理解,对单个 repos 的影响为零,并且非常适合分支切换(git-subtrees 尚不支持)。

    【讨论】:

    • 顺便说一句,git-submodules 有一个不同的目的:处理在一堆不同应用程序中使用的一堆库的依赖版本控制。您的构建系统可以使用项目级存储库。我的公司拥有数千个项目和数以万计的库,也有类似的东西,而且更漂亮。但这不是你遇到的问题。对于你的问题,我个人喜欢 git-submodules 的清晰,但我也理解其中的困难。
    • git-slave 正是我想要的。谢谢你指点给我。
    • 虽然git-slave 保持简单,但我认为一个很好的组合是使用git submodule foreach <some-command>。实际上,您可以配置子模块,以便 git submodule update 实际上合并(或变基!)所有分支。
    【解决方案3】:

    您仍然可以使用子模块。

    git submodule update

    将一次性更新所有子模块。

    【讨论】:

      【解决方案4】:

      我们尝试了“git submodule”,但并不令人满意。似乎 git submodule 是为变化不大的模块设计的。以下是对任何模块进行更改和推送更改的步骤:

      cd ~/dev/proj
      git checkout master
      git pull
      ... make changes to your files ...
      git commit -a -m "comment"
      git push
      cd ..   
      git commit -a -m "comment"
      git push
      

      这必须为 ~/dev 下的每个模块重复。对不起,但我觉得这很荒谬。在svn中,同样的事情是由

      完成的
      cd ~/dev
      svn commit -m "done in one line"
      

      我了解 git 相对于 svn 的好处,但是缺乏适当的子模块支持和缺乏良好的大文件支持可能会让我们从 git 切换到 svn(除非我们在这里找到解决方案 --- 我宁愿留下与 git)。老实说,我很惊讶这根本没有出现在 git 中。不同的项目一直共享共同的模块 [这些模块一直是实时的。

      我反对将 proj、ext 和 qa 放在同一个存储库下,因为

      • ext 将与其他项目(存储库)共享
      • qa 应该能够在没有代码的情况下检出(克隆)

      阿尔坦

      【讨论】:

        【解决方案5】:
        【解决方案6】:

        git-multi 就是答案。 https://github.com/grahamc/git-multi

        有 git-multi 设置,并在 '~/dev' 文件夹下克隆你需要的所有 repos。

        and from '~/dev' run "git multi pull" 或 "git multi status" 等命令,实习生在所有子repos中运行相应的命令。

        【讨论】:

          【解决方案7】:

          我遇到了同样的问题并编写了一个程序(bash 脚本)来做到这一点:gws

          大致思路如下:

          1. dev/.projects.gws中创建项目路径和url列表:

            work/proj  | https://...
            perso/ext  | git@github.com:...
            perso/qa   | https://...
            
          2. 使用gws 命令之一:
            • init:用于从当前文件夹树中的现有存储库自动创建.projects.gws 文件。
            • 更新:克隆缺少的本地存储库,例如在.projects.gws 中添加项目时。
            • status:显示所有存储库的状态(干净、未跟踪的文件、未提交的更改……)。
            • fetch:在所有存储库中执行 git fetch(然后 status 将能够检测到与原始存储库之间的差异,如果它在两者之间进行了修改)。
            • ff:在所有仓库中执行 git 快进拉取操作
            • 检查:验证工作区的状态(工作区中已知、未知、缺失的存储库)

          .projects.gws 文件随后可以使用 git 进行版本控制,并在许多计算机(工作、家庭、笔记本电脑...)上使用。也可以编写一个.ignore.gws 文件以在本地忽略一些带有正则表达式的路径,例如忽略家用计算机上work/ 文件夹中的存储库,^work/.*

          请参阅Readme 了解更多信息。

          我每天都在使用它,它符合我的需要(也许也适合你的需要)。请注意,我计划在有时间的时候用 Python 重写它(使用另一个名称)。原因是代码开始难以在 bash 中管理,我想添加更多功能(例如,添加对 mercurial、darcs 的支持...)。

          【讨论】:

            【解决方案8】:

            我编写了一个名为gita 的命令行工具来管理多个存储库。它并排显示已注册 repos 的状态,并从任何工作目录委托 git 命令/别名。例如

            颜色和额外符号显示本地/远程关系和编辑状态。

            如果你有很多 repos,你可以将它们分成不同的组并作用于组,或者为组设置上下文。

            【讨论】:

              【解决方案9】:

              恕我直言,子模块是这里的路。

              与其问你是否总是需要 X 和 Y 一起使用,不如问自己是否总是希望 X 和 Y 的完全相同的版本一起使用。

              Git 子模块为您提供了这个非常强大的工具,可以快速修复 X ​​中的错误,而无需同时更新 Y。

              例如,如果您正在开发在不同操作系统(例如 Mac OS X 和 Windows)上运行的产品,那么将特定于操作系统的代码分成单独的子模块可能是有意义的。如果不同的人在这些不同的操作系统端口上工作,则尤其如此。使用 git 子模块,您可以轻松地将一个操作系统的修复程序部署给您的客户,而无需在另一个操作系统上执行 QA 流程。

              另一个非常强大的用例是“工作区”模块。您只需一些本地模块(例如 /Workspace),然后添加您正在使用的所有依赖项。

              git submodules 的好处在于它不仅记录了您使用的模块,还记录了它们的具体修订。在修复错误时,我经常需要测试某些依赖项的特定版本 - git 子模块让我可以轻松地将这些记录在我的工作区模块的历史记录中,让我可以在以后轻松地回到那个确切的状态。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-07-01
                • 1970-01-01
                • 1970-01-01
                • 2010-10-23
                • 2020-12-15
                • 1970-01-01
                相关资源
                最近更新 更多