在一个仓库中嵌套另一个Git仓库

60

我想将 https://github.com/getyouridx/pychargify 克隆到我的django项目中,并且需要不时地拉取更新。

仅作澄清,我是否可以从django项目的根目录编写一个gitignore文件,例如: .gitignore: pychargify/.git,还是我应该注意其他问题?

5个回答

38

Git有一个在另一个存储库中拥有存储库的功能:submodules

git submodule add https://github.com/getyouridx/pychargify.git

确保阅读有关子模块的所有文档,因为在使用它们时会涉及一些怪癖,并且在对自己的存储库进行全新克隆以初始化子模块时需要执行其他步骤。

还要注意,所有子模块命令都必须在您存储库的根目录中执行。


非常好的答案,谢谢!不过你知道在子目录中安装它的诀窍吗?需要在 Django 应用程序中安装,而不是根目录... - null
2
git submodule add https://github.com/getyouridx/pychargify.git my-app/pychargify/ 给我返回了 "my-app/pychargify/ 已经存在于索引中"。 - null
@AdamGamble,你的代码库里可能已经有了一个 my-app/pychargify 文件夹,你需要删除它才能添加子模块。 - Andrew Marshall
很遗憾,事实并非如此 :-/ - null
奇怪,那个目录不存在,但当我尝试只输入“chargify”时,它却起作用了...很奇怪。 - null
2
@AdamGamble 也许你已经删除了目录,但没有从 Git 中移除?检查 git status 查看是否显示为已删除但未提交。 - Andrew Marshall

37
要在一个git repo中“嵌套”另一个git repo,请查看git子模块:http://git-scm.com/book/zh/v2/Git-工具-子模块 通过将pychargify作为django项目的子模块,您可以将django项目的特定修订版本与pychargify项目的特定修订版本关联起来。这非常有用。
我不确定您所描述的方法的危险性是什么,但它对我来说不可靠。我建议使用Git功能(子模块),该功能专门设计用于此类事情。

19

Git会自动忽略并且甚至不允许你添加任何名为.git的文件/文件夹。因此你可以在你的repo中添加另一个repo并进行操作。但是你可能需要忽略内部repo文件夹pychargify

当你想与他人分享repo并且他们将要克隆它时,就需要使用子模块。如果你只是想克隆内部repo并在本地repo上工作,而没有他人参与或者也不希望在其他地方拥有该repo,你并不需要子模块。


1
即使我需要与其他人共享内部存储库,只需进入该存储库并提交、推送或拉取不就可以了吗? - qed

15

Git子树

Git 子模块 是一种常见的方式,自引入以来已经取得了很大的进展,用于处理在一个项目(repo)中添加另一个项目(repo)的情况,正如其他答案所正确描述的那样。

然而,有人可以争辩说,子模块的方式不是唯一的方式,也不一定是正确的方式,这取决于已经建立的工作流程,原因多种多样,我不打算分析并且在几个页面上简要提及,例如这个这个。最重要的可能是这个:

当Git进入冲突解决模式时,它仍然不会更新子模块指针——这意味着当您在解决冲突后提交合并时,您会遇到相同的问题...:如果您忘记运行 git submodule update,则刚才回滚了分支可能已经进行的任何子模块提交。

当然,在完美的工作流程中,这种情况永远不会发生。

另一个重要原因是当写作时流行的PyCharm IDE(有一个非常旧问题)以及可能其他一些 IDE 并没有充分实现 Git 子模块,编码者将失去诸如 IDE 显示子模块中所有更改的方便功能等等。

因此,处理此问题的替代方法是使用子树。请注意,子树和子树合并不完全相同,但这又是另一回事了。在其第二版中,优秀的Progit书籍简要介绍了后者,但对前者没有单独的参考。

所以在一个实际的例子中,为了处理关注的情况,请假设一个subproject被消耗在一个project中:

$ git remote add subproject_remote (url)
# subproject_remote is the new branch name and (url) where to get it from, it could be a path to a local git repo

$ git subtree add —-prefix=subproject/ subproject_remote master
# the prefix is the name of the directory to place the subproject

$ git commit -am "Added subproject"
# possibly commit this along with any changes

如果子项目有变化,需要将它们合并到project中:

git subtree pull —prefix=subproject subproject_remote master

......或者相反(如果在project内的subproject中做出了更改):

git subtree push —prefix=subproject subproject_remote new_branch

这个链接中有一个分析性较强但比较混乱的教程。

这个功能也存在一些缺点,例如很多人认为工作流程繁琐且更加复杂,但这取决于特定已建立的工作流程。


根据您提供的链接,Jetbrains IDE从2018年开始支持子模块。 - Will Chen

14

将包含Git项目的文件夹添加到另一个Git项目中,可以像你期望的那样工作:它们之间没有直接交互,并且你可以通过在其中一个目录中工作来独立提交更改。你可以选择让“父”项目完全忽略内部文件夹,或者像它们是父项目的一部分一样提交子文件夹中的选定文件。

如果你选择后者,修改文件时,两个Git项目都会看到它被修改,你可以通过简单地在其中一个目录中工作来独立管理这些更改(提交更改)。

我假设你在使用命令行工具,在这种情况下,我相信XCode 7可以理解这种情况,并在文件上显示更改注释,只要该文件被视为一个或两个Git存储库中的已修改文件。

我发现以上步骤比处理子模块要简单,但其他人已评论了如何使用子模块,因此你可能需要进行比较。


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