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

Posted

技术标签:

【中文标题】如何将子模块添加到子目录?【英文标题】:How do I add a submodule to a sub-directory? 【发布时间】:2012-02-20 14:17:52 【问题描述】:

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

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

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

【问题讨论】:

进入 git repo 的根目录以获取子模块命令将不再是必需的(很快)。见my answer below git submodule add -b <branch> <url> <relative_path_4m_root> 【参考方案1】:

你进入~/.janus并运行:

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

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

【讨论】:

添加分支时添加分支似乎是个好主意,否则 HEAD 很容易分离: git submodule add -b [] 对我来说这是导致'subprojects' already exists in the index (我使用子项目作为目录名称)。相反,有帮助的是 VonC 在下面的答案,即执行 cd subprojects,然后在没有路径的情况下执行 git submodule add &lt;get@github …&gt;【参考方案2】:

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

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

(Bouke Versteeghcomments你不必使用/.,如snippets/.snippets就足够了)

见commit 091a6eb0feed820a43663ca63dc2bc0bb247bbae:

子模块:去掉顶层需求

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

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

签字人:John Keeping

取决于commit 12b9d32790b40bf3ea49134095619700191abf1f

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

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

【讨论】:

非常感谢!我注意到后面的/. 不是必需的,git 将创建目录 sn-ps 没有它。 @BoukeVersteegh 很有趣。我已将您的评论包含在答案中以提高知名度。 我使用的是 git 版本 2.7.4 但我仍然收到此错误消息 Relative path can only be used from the toplevel of the working tree 。我在做git submodule add ../../../functest @user3426358 是的,这是预期的:os 上面的答案是关于从主 repo 的任何子文件夹执行 git submoduel add 的能力,而不仅仅是从其根文件夹。 不是关于使用相对路径引用子模块远程 repo。如果这样做,您将收到您看到的错误消息。 @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” )【参考方案3】:

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

.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

也看到这个 - difference between .gitmodules and specifying submodules in .git/config?

【讨论】:

【参考方案4】:

我也遇到过类似的问题,但使用 GUI 工具将自己逼入绝境。

我有一个子项目,其中包含一些文件,到目前为止我只是复制而不是检查到他们自己的 git 存储库中。我在子文件夹中创建了一个 repo,能够提交、推送等就好了。但是在父 repo 中,子文件夹没有被视为子模块,并且它的文件仍在被父 repo 跟踪 - 不好。

为了摆脱这种混乱,我不得不tell Git to stop tracking the subfolder(不删除文件):

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,是最干净的选择。

【讨论】:

【参考方案5】:

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

干杯

【讨论】:

以上是关于如何将子模块添加到子目录?的主要内容,如果未能解决你的问题,请参考以下文章

sh 将子模块添加到git项目

Git:将子模块文件检出到单个目录中

反应路线将子路线移动到单独的模块?

将子模块更新为最新的提交

如何从 mysql 将子类别加载到 joomla

如何按顺序将子视图添加到 UIScrollView