如何将git子模块更改为指向子文件夹?

145

浏览了子模块教程后,我基于boto项目创建了一个子模块。然后,我发现我只需要该项目的一个子集 - 具体来说是boto文件夹。

我想将我的子模块指向这个文件夹。当我查看.gitmodules文件时,我看到:

[submodule "backup/src/boto"]
    path = backup/src/boto
    url = https://github.com/boto/boto.git

我应该使用什么URL代替https://github.com/boto/boto.git?更改URL后,我是否应该在本地删除boto文件夹并重新拉取?


5
这并不是你想要的子模块,但你可以看一下 git subtree(https://github.com/apenwarr/git-subtree)。 - Cascabel
2
我最终做的是将整个子模块作为一个整体,并告诉IntelliJ boto文件夹是一个“源代码文件夹”,以便它可以找到其中的包。 - ripper234
30
我无法相信 Git 原生不支持这个......哎呀。 - rogerdpack
4
找到了一个类似的问题 - https://dev59.com/h3NA5IYBdhLWcg3wBpDs - sashoalm
5个回答

86

恐怕子模块的URL总是指向仓库 - 无法指定只想要存储库的子文件夹,就像Git一般不支持“狭窄克隆”。

如果你不能接受将整个仓库作为子模块,则可以创建一个新仓库,从boto中进行克隆,然后设置cron作业:

  1. git fetch 将该仓库获取到一个目录中
  2. 使用git filter-branch更新一个分支,在该分支中子目录位于顶层。
  3. 将该仓库的该分支添加为子模块。但是,所有这些都有点棘手,我更倾向于将整个仓库作为子模块。

34

您不能仅克隆存储库的一部分。这是因为 Git 将存储库视为一个整体对象:当您获取它时,您获取了全部内容。

因此,在此处的解决方案是在另一个目录中提取子模块,然后使用符号链接来实现您的目标。


我在 Windows 中有符号链接...也很好用。这是因为我在我的机器上有 msys,所以我可以像在 Linux 中一样使用 ln -s - kumarharsh
7
Vista和Windows 7自带MKLink。我使用它。http://www.howtogeek.com/howto/windows-vista/using-symlinks-in-windows-vista/ - Angel S. Moreno
1
你可以使用硬链接代替。 - KindDragon
1
@KindDragon:你不能创建目录的硬链接。 - Peter V. Mørch

24

这里所有的答案都相当陈旧了。你可以使用更新的git sparse-checkout命令,文档在这里这篇文章中有更多示例,以获取仓库的部分内容。如果你只想从一个较大的 git 项目中获取一个或两个目录,这是非常有效的。

TLDR:

使用更新的git sparse-checkout命令来获取 git 项目的部分内容。

git sparse-checkout init --cone
git sparse-checkout set <dir1> <dir2> ...
git checkout main

4
如果文件在你的(单一)代码库中,那看起来很好。但是如果你想要的文件是不同单一代码库的子集 - 也就是子模块的子文件夹呢? - FuriousGeorge
文章中提到,如果你运行了git sparse-checkout set A/B,那么Git将包括文件名为A/B/C.txt(A/B的直接子级)和A/D.txt(A/B的直接同级),以及E.txt(A的直接同级)。就我个人而言,我认为这种方式有限制:我只想要A/B/C.txt。在问题的背景下,我的看法是:“sparse-checkout允许您从您的repo中排除根子目录。submodule允许您在您的repo中的任何位置包含另一个repo的根目录。” - Daniel Kaplan

18
您需要做的是在子模块中创建一个分支,将文件夹移动到上级目录并删除不需要的内容。然后您可以管理该分支。如果您想要推送您的更改,您应该首先进行回退合并。Git 将知道您移动了文件并成功地完成合并。希望这能帮到您。

2
什么是“回溯合并”?你能举个例子吗? - Sukima
请问您能否在这种情况下添加一些“回溯合并”的示例? - Xiao
通常情况下,当你尝试通过从主干分支合并最新更改来保持功能分支的最新状态时,就会出现这种情况。这是不好的,因为它将你的分支与其他人的工作联系在一起。如果产品需要你的分支,但不需要已经集成到主干分支中的其他分支之一,那么这是不可能的。 - Adam Dymitruk
1
有趣的想法,有人尝试过吗?我很快就要尝试了,但仍然不确定“回溯合并”是否可以清晰自动化... - moudrick
1
在我的具体情况中,我最终使用git filter-branch --subdirectory-filter我收藏列表中的这个要点移动了包含历史记录的文件夹,因为我实际上并不需要合并回去...老实说,我对@Artfaith的这个案例没有更多的细节记忆。 - undefined
显示剩余2条评论

4
将子模块保存到“submodules/”目录中,然后创建一个符号链接:
git submodule add https://github.com/user/repo submodules/repo
ln -s submodules/repo/subdir .
git add subdir

结果:

./
  submodules/
    repo/
      subdir/

  subdir  -->  ./submodules/repo/subdir

这种方法的一个好处是可以在多个子目录中重复使用。

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