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

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

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

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

323408 次浏览

你进入~/.janus并运行:

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

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

注意,从git1.8.4(2013年7月)开始,你不再需要回到根目录。

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

(Bouke Versteegh 评论,你不必使用/.,因为在snippets/.: snippets就足够了)

看到提交091年a6eb0feed820a43663ca63dc2bc0bb247bbae:

子模块:删除顶层需求

使用新的rev-parse --prefix选项来处理给予子模块命令的所有路径,放弃从存储库顶层运行的要求。

由于相对子模块URL的解释取决于是否配置了"remote.origin.url",当不在工作树的顶层时,显式地阻塞"git submodule add"中的相对URL。

署名:John Keeping

取决于提交12 b9d32790b40bf3ea49134095619700191abf1f

这使得'git rev-parse'的行为就像从存储库的指定子目录中调用一样,不同的是它打印的任何文件路径都以工作树顶部的完整路径作为前缀. git rev-parse

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

我也遇到过类似的问题,但却因为GUI工具而陷入了困境。

我有一个子项目,其中有几个文件,到目前为止,我只是复制,而不是检查到他们自己的git repo。我在子文件夹中创建了一个repo,能够提交,推送等。但是在父repo中,子文件夹不被视为子模块,它的文件仍然被父repo跟踪——这不好。

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

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

然后我必须告诉它那里有一个子模块(如果git当前正在跟踪任何东西,你就不能这样做):

proj> git submodule add ./ui/jslib

更新

处理这个问题的理想方法包括更多的步骤。理想情况下,现有的repo被移出到它自己的目录中,不包含任何父git模块,提交并推送,然后作为子模块添加,如:

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

这将把git repo克隆为一个子模块——这包括标准的克隆步骤,但也包括其他一些更模糊的配置步骤,git代表你让这个子模块工作。最重要的区别是它在那里放置了一个简单的.git文件,而不是一个.git目录,其中包含了一个指向真正git目录所在位置的路径引用——通常在父项目根.git/modules/jslib。

如果你不这么做,它们会很适合你,但一旦你做出承诺并推动父母,其他开发者就会去拉他们的父母,你只会让他们的生活变得更加艰难。只要你在一个包含自己的.git目录的目录的子文件夹中有一个完整的.git目录,他们就很难在你的机器上复制你的结构。

move, push, git add submodule,是最干净的选项。

对于那些和我一样喜欢手动编辑配置文件的人来说,添加(或修改)以下内容也可以达到目的。

. /配置(个人配置)

[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中指定子模块的区别?

一行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

干杯