如何`git submodule add`现有的子存储库?

Posted

技术标签:

【中文标题】如何`git submodule add`现有的子存储库?【英文标题】:How to `git submodule add` Existing sub Repository? 【发布时间】:2015-12-22 22:08:20 【问题描述】:

问题

如何将现有的子存储库添加为 git 中的子模块?

为什么

我有一个私有的codespace 超级模块,子模块随机分布:

codespace (git repo, private)
├── Archived_projects (git repos)
└── Projects
    ├── project-foo (git repo)
    └── project-bar (git repo)

有时子模块的提交尚未准备好推送。但我希望在推送超级模块codespace 时保存它们。codespace 是克隆到c9.io 工作区或其他地方的存储库。

我做什么

linus@machine /cygdrive/f/__Storage__/Workspace
$ git clone https://github.com/octocat/Spoon-Knife.git
Cloning into 'Spoon-Knife'...
$ cd Spoon-Knife/
$ git clone https://github.com/octocat/Spoon-Knife.git ./foo/bar
Cloning into './foo/bar'...
$ git add .

来自 cmd.exe

> git submodule add https://github.com/octocat/Spoon-Knife.git ./foo/bar
'foo/bar' already exists in the index
> cat .gitmodules
cat: .gitmodules: No such file or directory

来自 cygwin.exe (bash)

$ git submodule add https://github.com/octocat/Spoon-Knife.git ./foo/bar
': not a valid identifier/Git/mingw64/bin/gettext.sh: line 89: export: `sm_path
'' already exists in the index
$ cat .gitmodules
cat: .gitmodules: No such file or directory

参考

git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
              [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]

<repository> is the URL of the new submodule’s origin repository.

<path> is the relative location for the cloned submodule to exist in the superproject. If <path> does not exist, then the
submodule is created by cloning from the named URL. If <path> does exist and is already a valid Git repository, then this is
added to the changeset without cloning. This second form is provided to ease creating a new submodule from scratch, and
presumes the user will later push the submodule to the given URL.

In either case, the given URL is recorded into .gitmodules for use by subsequent users cloning the superproject. If the URL
is given relative to the superproject’s repository, the presumption is the superproject and submodule repositories will be
kept together in the same relative location, and only the superproject’s URL needs to be provided: git-submodule will
correctly locate the submodule using the relative URL in .gitmodules.

如果 &lt;path&gt; 确实存在并且已经是一个有效的 Git 存储库,则将其添加到变更集中而不进行克隆。

为什么这在我的情况下不起作用?

【问题讨论】:

This might help。将 repo 从工作树中移出,添加子模块,修复 url 【参考方案1】:

您无需先手动克隆。运行git submodule add [url] [path] 后运行git submodule update,它将为您克隆/拉取所有子模块。

【讨论】:

我已经有包含克隆和修改数据的存储库。理想情况下,我希望能够将带有超级模块的子模块推送到服务器。好吧,如果不可能,我接受你的回答。 我有同样的问题,已经克隆并修改了一些文件,如何将这个修改后的 repo 作为子模块添加到另一个 git repo?【参考方案2】:

一种方法是手动创建.gitmodules 文件。

格式如下:

[submodule "path/to/submodule1"]
    path = path/to/submodule/1
    url = git@github.com:user/submodule1
[submodule "path/to/submodule2"]
    path = path/to/submodule/2
    url = git@github.com:user/submodule2

请注意,您必须运行

git submodule sync

应用更改

【讨论】:

注意,它是 .gitmodules. 不幸的是,这似乎没有任何作用。 @DustWolf 您需要运行 git submodule sync 才能应用更改 @Rufus 我没试过,但听起来可能。我最终使用了这个解决方案:***.com/a/30675130/2897386 ...这似乎更安全。【参考方案3】:

git submodule add 检测给定子模块的路径是否存在并包含初始化的 git 存储库,因此无需担心。我遇到了类似的问题,所以我写了一个(hacky)脚本来处理这个问题。

#!/bin/bash
# save super directory
currentDir=`pwd`
# get all the git repos inside (except .) and format them 
# the way git does
gitDirs=`find -type d -name ".git" | sed -e 's|.git$||' -e 's|./||' -e 's|/$||' | grep -v "^$"`

for i in $gitDirs[@]
do
        echo "dealing with $i now"

        cd $i 
        # get the remote url for each submodule
        fetchUrl=`git remote -v | awk '/fetch/ print $2'`
        # for my purposes repos without remotes are useless
        # but you may have a different use case
        if [[ -z $fetchUrl ]]
        then
                echo "fetch url not found for this directory"
                continue
        else                                                      
                echo "got a fetch url of $fetchUrl for git repo $i"                                                                 
        fi                                                        

        cd $currentDir
        # make sure it isn't tracked as a submodule already                                                         
        existing=`grep -A5  $i ./.gitmodules | grep $fetchUrl`    

        if [[ -z $existing ]]                                     
        then                                                      
                echo "does not exist in .gitmodules yet, will create now"
                # if it doesn't exist yet then create it
                git submodule add $fetchUrl $i
        else
                echo "$i is already present as a submodule with fetch url: $fetchUrl"
                echo "The command we would have used is: git submodule add $fetchUrl $i"
        fi
done

【讨论】:

【参考方案4】:

你做错了什么

$ git add .

这会将所有内容以及foo/bar 添加到当前存储库的索引中(准备好提交)。

如果你不这样做并继续

$ git submodule add https://github.com/CarloWood/XYZ.git foo/bar

那应该可以了;这将检测到 foo/bar 是已经克隆的 存储库并将其作为子模块添加到当前存储库。

请注意,不需要先克隆。您明确表示您已经这样做了,但为了让其他读者清楚,我想指出,如果您也省略了 git add . 之前的克隆(所以现在根本没有 foo/bar)那么上面的git submodule add ... 会看到还没有任何东西,然后简单地为你克隆它。

请注意,方法之间存在细微差别。如果您从克隆开始,则foo/.git 将是一个目录,而如果您使用git submodule add 进行克隆,则此.git 存储库将放在父项目的.git/modules/foo 中,foo/.git 是一个包含通往那的道路。但是没有真正的区别,因为使用.git 的文件指向其他任何地方是通用的,可以在任何地方使用; .git 是一个文件或目录,你无法得出任何结论。

【讨论】:

【参考方案5】:
    从索引中删除文件foo/bar:git rm -f --cached foo/bar git submodule add https://github.com/octocat/Spoon-Knife.git ./foo/bar

【讨论】:

【参考方案6】:

为现有的存储库增加 Carlos Answer。它已经包含它的 URL。你可以简单地

 git submodule add $(cat repodir/.git/config  | grep url | cut -d '=' -f 2) reponame

【讨论】:

也许您可以使用 git config 来读取 url:git submodule add $(git -C repodir config remote.$(git -C repodir config branch.master.remote).url) repodir,而不是自己解析配置文件。这将选择 master 分支的远程跟踪分支的 url。 (即使存在多个遥控器也可以工作,您的示例在这种情况下不起作用。)(git -C somedirectory 表示 git 的行为 as if started from within somedirectory

以上是关于如何`git submodule add`现有的子存储库?的主要内容,如果未能解决你的问题,请参考以下文章

git submodule add子模块的添加,--recurse-submodules递归克隆子项目

git submodule add子模块的添加,--recurse-submodules递归克隆子项目

git submodule

git add submodule

git add submodule

git add submodule