如何使用Git创建一个仓库的层次结构?

8

我有一个项目,其层次结构如下:

Tharwa
|_tharwa-backend
|_tharwa-web
|_tharwa-mobile 

每个子文件夹都是自己的存储库;我想创建一个名为Tharwa的存储库,将所有内容整合在一起。
但是,我有以下限制:
  • I don't want to put them in the same repo as subfolders because each have its own dependencies and configuration files, and also I don't want to have their commits mixed up.

  • I don't want to leave them as separate repos since I have issues on the parent repo that might require work to be done on ,say, both the back end and mobile repos,and i would like the have the issue solved on the same branch, for example :

    __________________________ master
     \________________________ develop
           \______/ login
    
我的问题是,我该如何使这种情况成为可能?我错在哪里了?
如果我的表述不够清晰,请告诉我。 谢谢你的帮助。

1
Git支持所谓的“子模块”,您可以在一个存储库中包含对其他存储库的引用。这个引用甚至可以指向特定的提交,允许您对子模块的使用进行版本控制。您的主要存储库几乎可以没有任何代码,只需将所有子项目链接在一起即可。 - GolezTrol
@GolezTrol,我尝试着玩一下子模块,但是遇到了一些奇怪的分离头问题,不太理解。而且我看到有人说子模块很危险。它们支持分支吗?如果我在主仓库上创建一个分支,那么所有子模块中都会创建这个分支吗? - Amine Birouk
如果您想将一个分支“应用”于所有3个,您需要将它们每个都作为子目录。这与您的“不混合提交”愿望相矛盾,但我认为您的两个约束有点不兼容,因此您需要在两者之间进行选择。对于您的第一个要点,子模块可能是一种解决方案,但通常不建议使用,因为它会导致混淆和复杂性。 - Patrick Mevzek
@PatrickMevzek,人们通常如何处理这些类型的项目?我还是新手,工作流程对我来说仍然有点模糊。 - Amine Birouk
我不相信有一种适用于所有情况的唯一正确方式。在我看来,你对“提交不混合”的限制似乎是出于某种恐惧,但我不知道原因,而你似乎暗示要同时针对3个项目进行工作。所以我会只有一个仓库,里面有3个目录,就这样。请注意,这也取决于每个部分如何发布和部署(一起、分开等)。另外,简单的方法是:尝试一个案例,并在日常生活中查看它是否适合您。您随时可以更改! - Patrick Mevzek
@PatrickMevzek 好的,谢谢您的回复。 - Amine Birouk
2个回答

10
基本上有三种方法可以看待这个问题:
  1. 一个仓库,其中包含三个目录,每个目录对应一个项目
  2. 一个仓库,可能几乎为空,其中包含三个git子模块(因此每个子模块都是一个独立的仓库,但与主仓库相连)
  3. 三个完全独立的仓库
我不知道你的“我不想让他们的提交混在一起”的限制来自哪里,也许只是因为你还不太了解git。现在只需要注意一下,在git中你有强大的工具和选项来查看提交,按日期、作者、路径、内容等进行过滤。所以我认为这不是什么需要担心的事情。相反,这使你可以清楚地显示,一个唯一的提交,第一个项目中的文件X与第二个项目中的文件Y同时发生了变化(例如,因为你更改了API,所以你需要同时更改API的生产者和消费者,并且这应该反映在一个提交中)。
但是,如果你想要严格的提交隔离,那么选项3和选项2中都有,而选项1中则没有:在那里,一个提交可能涵盖任何一个子项目的更改。

至于你的第二个限制条件,选项1可以立即实现,选项2有点可能,但选项3肯定不行。

Git子模块本身就带有一些限制条件,因此值得单独讨论。在大规模使用之前,请确保阅读和学习相关内容。 以下是一些有趣的链接,除了官方文档(第一个链接)。

关于你的特定问题,有关子模块和分支,请查看这个问题及其答案:Git submodules: Specify a branch/tag 正如我在评论中写的那样,事情也取决于你如何打包和分发这个软件。它总是作为一个完整的代码部署(选项1和2更有意义),还是可以只发布其中一个项目(选项3更有意义)。
请注意,我说“更有意义”,因为这并不是非黑即白的问题,你可以在任何选项中实现你的目标,只是妥协的方式不同。
这也取决于将在其中工作的开发人员团队。他们在git方面的知识水平如何?对于git初学者而言,子模块并不是我推荐的东西。以及提交如何在远程仓库之间推送/拉取?在选项1中,你只需要处理一个仓库,在选项2中也是如此,但你需要更新子模块(请参阅文档),在选项3中,你需要处理3个单独的仓库。
可能还有其他需要考虑的侧面,但如果您从空内容开始,则它们可能是不相关的。比如大小。有些仓库可能包含很多历史记录,这会影响到例如git clone(所以在这种情况下,如果一个仓库很大,可以使用单独的仓库来避免影响其他仓库)。
您似乎提到了一种工作流程,就像http://nvie.com/posts/a-successful-git-branching-model/中描述的那样,这是一个好的开始。如果您想坚持这个模型,选项1将很容易实现,选项2基本上是可能的但不完全准确,而选项3则不可能。(也可以参考https://www.atlassian.com/git/tutorials/comparing-workflows了解其他可能的工作流程)
我真的觉得您的两个约束条件是朝着相反的方向发展的,因此您需要看看哪个比另一个更重要。
对于我自己而言,在没有整个情况的情况下,我更喜欢选项1,因为它似乎是最灵活的(并且您可以轻松地切换到选项2或3)。

哈哈!- “powerfool 工具”。这是故意的吗?Git 是如此强大,有时让我感觉像个傻瓜 - 所以它确实与我共鸣。 - Craig Hicks
1
@CraigHicks 那是一个诚实的错误(英语不是我的母语),因此并不是故意的。但现在听起来对我很有趣,所以我会让它保持这样。感谢您的评论! - Patrick Mevzek

2
我不希望将它们作为子文件夹放在同一个仓库中,因为每个都有自己的依赖和配置文件,而且我也不想让它们的提交混在一起。
好的,你不想让它们的提交混在一起。
我不想将它们留作单独的仓库,因为我在父仓库上有问题,可能需要在后端和移动端仓库上做出修改,我想在同一个分支上解决问题...
...除非你确实想让它们的提交混在一起。 ;)
我哪里错了?
如果你经常需要同时更改多个仓库,你可能需要考虑它们是否实际上是单个仓库。有两种处理这种情况的好方法,但子仓库不是其中之一。

一个仓库

将它们合并成一个单一的代码库。如果它们都是同一项目的一部分,并且它们之间存在相互依赖的更改,则它们是一个单一的代码库。它们可以是具有自己配置和依赖项的子文件夹,这对于需要共同开发但需要进行分发的大型项目来说是相当常见的。

缺点是开发人员很可能会利用此功能,将客户端代码与后端紧密绑定。如果项目之间没有明确的分离,则后端API可能会变得松散。客户端更有可能利用未记录的后端功能,使整个系统变得脆弱且难以更改。添加新的客户端(例如tharwa-api)将变得更加困难。

如果有第三方为tharwa-backend编写自己的客户端,则他们处于劣势。 clientweb 处于特权位置,它们可以与 backend 同步。第三方开发者就没有那么幸运了,你的项目将更难贡献。

一旦将项目组合在一起,您就不太可能再将它们分开。


许多仓库,严格的依赖关系。

另一种方法是通过每个仓库将其他仓库视为正常依赖项来更严格地执行各个部分之间的封装。在您的login示例中...

  • backend上实现、测试和提交更改。
  • 发布backend,即使只是用于内部分发。
  • 针对新的backend测试webmobile,以确保向后兼容性得到维护。
  • 一些依赖机制允许直接从Git仓库获取依赖关系。
  • 使webmobile更新其backend依赖项并使用新功能。

现在开发人员更难作弊了。发布的额外步骤(即使只需一两分钟)提供了一个“空气间隙”。backend必须开发自己的单元、集成和验收测试;它不能依靠客户端为它们完成这些工作。客户端必须更加健壮,并更加严格地遵守后端API。通过解耦后端和客户端,更容易对每个部分的内部进行重大更改。

开发人员仍然可以进行锁步更改,但现在它们是明确的。使它们明确会阻止它们的使用,防止开发人员变得懒惰。
但这确实增加了一些额外的开销。后端更改必须经过充分的思考、开发和文档化。后端API必须更加完善和健壮。客户端必须更加密切地遵守API。所有这些都是良好的软件工程,将在中长期内加快速度。

为什么不使用子模块?

子模块提供了单个存储库的大部分优点,但增加了一个令人困惑的功能。它还提供了单个存储库的所有缺点,再加上一个:缺乏协调。

在单个存储库中,一个提交就是一个提交。一个分支就是一个分支。而使用子模块,则很难通过查看单个存储库来确定哪些提交必须在所有存储库之间进行协调。这些协调提交可以在任何时候发生,没有警告,并且很难知道。

您需要一些程序和机制来跟踪和协调这些提交。您可以通过试错自己构建所有内容,也可以使用现有的发布依赖系统。


你选择哪种取决于你的项目。然而,我建议你尝试完全解耦,并看看效果如何。这有助于促进良好的软件工程实践。而且你总是可以稍后将它们重新组合在一起,反过来则很困难。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接