Git存储库中的Git存储库

31

我有一个包含Git存储库的Git存储库。

repo1/
     .git/
     files
     repo2/
          .git/
          files
     files

这种架构是否可行?


4
我应该认真考虑使用子模块。 - MP0
你为什么要考虑这样做?可能有其他选择。 - John Kane
4
当使用作为单独存储库托管的框架和框架组件时,这种“问题”会自然而然地发生。例如,如果你检出WordPress或Vagrant + WordPress项目,然后检出WordPress主题和可能包含在第一个存储库的文件结构中的某些插件。每个组件通常都是它们自己的git存储库,而不是子模块。我只需将每个这些第三方存储库的根目录添加到其父存储库的gitignore文件中即可。 - mikkelbreum
6个回答

22
您可以拥有嵌套的 Git 子仓库:
父仓库将简单地忽略嵌套仓库。

jleedev 评论并通过此 gist 脚本 进行说明,说明父仓库将通过 一个 gitlink 跟踪嵌套仓库的状态。
(gitlink=另一个存储库中引用提交的对象的 SHA-1。Git 链接只能通过 SHA 或通过提交标记指定。
gitlink 有一个特殊模式 '160000',用于子模块,但也适用于简单的嵌套仓库)。
然而,通常的命令不会承认嵌套的子仓库:addcommit 只会应用于一个仓库,而不是其他仓库。 git submodule 允许从父仓库引用嵌套子仓库,并保持对子仓库的精确引用。
另一种选择可能涉及:
  • 两个独立的 Git 仓库(不是嵌套的)
  • 从一个指向另一个特定部分的符号链接(Unix 和 Windows Vista+ 都有符号链接)

2
父存储库不会忽略它;它将使用gitlink跟踪HEAD。 - Josh Lee
2
很不幸,它的文件很少;大部分文档都是关于子模块而不是gitlinks的。在“Documentation/”中搜索160000gitlink。 这里是一个关于gitlinks行为的示例 - Josh Lee
4
值得注意的是,gitlink 是树/索引条目,而子模块是使克隆和同步您的 gitlinks 成为可能的用户界面。然而,该文档并没有真正解释这一点。 - Josh Lee
2
@jleedev:太好了。我已经把你的评论集成到我的答案中,并添加了对 git fast-import 手册的链接,这是 Git 中唯一明确提到 gitlink 是什么的文档。 - VonC
3
如果你执行 git add . 或者 git add inner-repo,结果会是一个 git 链接,就像这里描述的那样。但是,如果你执行 git add inner-repo/(带有斜杠),那么它会添加仓库内部的文件,并开始跟踪它们,就像跟踪任何其他文件一样(除了 inner-repo/.git,它会被忽略)。因此,结果是两个仓库单独跟踪文件,它们不知道彼此的存在。 - spelufo
显示剩余7条评论

10
你正在尝试实现一个叫做"子模块"的功能。 请查看Git 工具 - 子模块,了解它的工作方式。

好的,我会处理这个问题,明天会有更多实验结果 :3 - MP0

4

我使用这种结构已经有一段时间了,子仓库目录在外部仓库的.gitignore文件中指定。

这让我的编辑器(PhpStorm)的git工具感到困惑,它总是希望提交到外部仓库,但除此之外都能正常工作。我将整个外部仓库(包括所有内部仓库)作为一个项目加载到编辑器中。这样就可以在处理内部仓库时轻松搜索和查看外部仓库的代码。

我在任何我正在处理的仓库中使用Git bash进行所有Git操作。

子模块可能是更好的方法。我还没有时间去调查它们是否能更好地与PhpStorm配合使用。


2

是的,您可以使用这种模式。我过去曾将SVN外部引用带入git-svn克隆中。现在子模块可能处理得更好,但当时不适合我的需求。

您需要将以下内容添加到repo1/.git/info/exclude中,以确保repo2中的更改不会与repo1混合:

repo2

1
我也同意罗纳德·威廉斯的回答。Git子模块的主要目的是更新从外部世界获取的代码,而无需在该代码被更新后提交更改。
Composer软件包管理系统也是如此。实际上,他们也不建议提交这些更改,并在项目根目录中的.gitignore中忽略 vendor 文件夹。
如果您尝试提交此文件夹,则会成为噩梦,因为其中一些 vendor / some_repo 可能是开发版本,因此它们具有.git文件夹,即使您没有使用 git submodule add 添加它们,所有这些软件包都将成为子模块。如果您修改嵌套的.git存储库中的 some_file ,则可能会看到类似于此的内容:
~/project_root $ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#   (commit or discard the untracked or modified content in submodules)
#
#    modified:   vendor/nested_repo (modified content)

请注意子模块中的修改内容,并且在输出中看不到“some_file”名称。相反,您会看到“(modified content)”提示,因为根项目.git将vendor/nested_repo视为子模块,并且不跟踪该文件夹中的单个文件。
如果您运行git add --all命令,则在提交vendor/nested_repo更改之前不会得到任何结果,只有在此之后才能提交根存储库中的更改。
不要这样做。相反,如果您想将整个项目保留为.git存储库(任何存储库,而不仅仅是Composer构建的存储库),这有时非常方便,请在初始提交之前将此条目添加到根.gitignore中。
.git
!/.git

很遗憾,为了让整个配方起作用,您需要为每个后续想要单独修改的嵌套存储库运行git add命令。请注意,存储库路径中的尾部斜杠是必须的
~/project_root $ git add vendor/some_repo/ vendor/another_repo/

然后修改vendor/some_repo中的some_file,看看有什么不同:
~/project_root $ git status
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#    modified:   vendor/some_repo/some_file

那么,您可以像往常一样在project_root中运行git add --all,然后再运行git commit "Changes ..."

0

还有软件包管理解决方案。

Git子模块确实可以让您按照所描述的架构进行开发,而Git子树提供了类似的解决方案,许多人更喜欢使用它。

在我看来,软件包管理软件是任何复杂项目不可或缺的一部分。我喜欢Composer,因为它支持直观的工作流程。

不幸的是,PhpStorm不支持Git子模块:

应该支持Git子模块 (IDEA-64024)


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