如何将子模块添加到子目录?
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 belowgit 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 <get@github …>
。【参考方案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
干杯
【讨论】:
以上是关于如何将子模块添加到子目录?的主要内容,如果未能解决你的问题,请参考以下文章