如何将子模块添加到子目录?


309

我有一个git repo,里面~/.janus/有很多子模块。我想在中添加子模块~/.janus/snipmate-snippets/snippets/,但是git submodule add <git@github.com:...>在snipmate-snippets目录中运行时,出现以下错误消息:

You need to run this command from the toplevel of the working tree.

所以问题是:如何将子模块添加到snipmate-snippets目录中?


不再需要(很快)转到git repo的根目录以获取子模块命令。请在下面
— VonC

3
git submodule add -b <branch> <url> <relative_path_4m_root>
— parasrish

Answers:


437

您进入~/.janus并运行:

git submodule add <git@github ...> snipmate-snippets/snippets/

如果您需要有关子模块的更多信息(或通常的git),ProGit会非常有用。


在添加时添加分支似乎是个好主意,否则HEAD容易分离:git submodule add -b <branch> <repository> [<submodule-path>]
— deann

1
对我来说,这是造成的'subprojects' already exists in the index (我使用子项目作为目录名)。取而代之的是,下面的VonC答案(即做)cd subprojects,然后git submodule add <get@github …>没有了路径。
— Hi-Angel

83

请注意,从git1.8.4(2013年7月)开始,您将不必再返回到根目录。

 cd ~/.janus/snipmate-snippets
 git submodule add <git@github ...> snippets

(Bouke Versteegh 评论,你不必使用/.,如snippets/.:snippets就够了)

参见commit 091a6eb0feed820a43663ca63dc2bc0bb247bbae:

子模块:删除顶级需求

使用new rev-parse --prefix选项来处理所有赋予submodule命令的路径,从存储库的顶层删除运行它的要求。

由于相对子模块URL的解释取决于是否remote.origin.url配置了“ git submodule add”,因此,如果不在工作树的顶层,则在“ ”中显式阻止相对URL 。

签名人:John Keeping

取决于提交12b9d32790b40bf3ea49134095619700191abf1f

这使得' git rev-parse'的行为就像是从存储库的指定子目录中调用的,区别在于它打印的任何文件路径都以从工作树顶部开始的完整路径作为前缀。

这对于s​​hell脚本很有用,在shell脚本中,我们可能想移到cd工作树的顶部,但需要处理用户在命令行上给出的相对路径。


十分感谢!我注意到尾部/.没有必要,git会在没有尾部的情况下创建目录片段。
— Bouke Versteegh 2014年

@BoukeVersteegh有趣。我已将您的评论包括在答案中,以提高知名度。
— VonC 2014年

我使用的是git 2.7.4版,但仍然收到此错误消息Relative path can only be used from the toplevel of the working tree。我在做git submodule add ../../../functest
— FlyingAura

@ user3426358是的,这是可以预期的:上面的回答有关从主仓库的任何子文件夹(而不是从其根文件夹)添加git子模的能力。这与使用相对路径引用子模块远程仓库无关。如果这样做,您将收到看到的错误消息。
— VonC

@ user3426358顺便说一句,该错误消息(您看到的是:“ Relative path can only be used from the toplevel of the working tree“)不是来自原始问题(“ You need to run this command from the toplevel of the working tree”)的错误消息
— VonC 2016年

17

我遇到了类似的问题,但是使用GUI工具使自己陷入困境。

我有一个子项目,里面有几个文件,到目前为止,我只是复制而不是检查自己的git repo。我在子文件夹中创建了一个存储库,能够进行提交,推送等工作。但是在父仓库中,子文件夹并未被视为子模块,并且其文件仍被父仓库跟踪-不好。

为了摆脱混乱,我不得不告诉Git停止跟踪子文件夹(不删除文件):

proj> git rm -r --cached ./ui/jslib

然后,我不得不告诉它那里有一个子模块(如果git当前正在跟踪任何内容,则无法执行该操作):

proj> git submodule add ./ui/jslib

更新资料

解决此问题的理想方法涉及更多步骤。理想情况下,将现有存储库移到其自己的目录中,不带任何父git模块,进行提交和推送,然后将其添加为子模块,例如:

proj> git submodule add git@bitbucket.org:user/jslib.git ui/jslib

这会将git repo克隆为子模块-这涉及标准的克隆步骤,还涉及git代表您执行的其他一些晦涩的配置步骤,以使该子模块正常工作。最重要的区别是,它在其中放置了一个简单的.git文件,而不是.git目录,该目录包含指向实际git dir所在位置的路径引用-通常位于父项目根目录.git / modules / jslib中。

如果您不采用这种方式做事,他们会为您工作的很好,但是一旦您提交并推动了父项,而另一个开发人员去拉扯该父项,您就使他们的生活变得更加艰难。只要您在包含其自己的.git目录的dir子文件夹中具有完整的.git目录,它们将很难复制您计算机上的结构。

因此,移动,推送,git add子模块是最干净的选择。


16

对于那些喜欢手动编辑配置文件的怪癖的人,添加(或修改)以下内容也可以解决问题。

.git / config(个人配置)

[submodule "cookbooks/apt"]
    url = https://github.com/opscode-cookbooks/apt

.gitmodules(提交的共享配置)

[submodule "cookbooks/apt"]
    path = cookbooks/apt
    url = https://github.com/opscode-cookbooks/apt

看到这很好-.gitmodules和在.git / config中指定子模块之间的区别吗?


2

单行bash脚本可帮助Chris回答上面的问题,因为我已经将自己画在角落,也使用Vundle更新我的.vim脚本。 DEST是包含子模块的目录的路径。做完之后再做git rm -r $DEST

DEST='path'; for file in `ls ${DEST}`; do git submodule add `grep url ${DEST}/${file}/.git/config|awk -F= '{print $2}'` ${DEST}/${file}; done

干杯

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.