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

vawmfj5a  于 2022-12-10  发布在  Git
关注(0)|答案(8)|浏览(194)

问题

如何在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.

如果<path>确实存在并且已经是有效的Git储存机制,则会将其加入变更集而不进行复制。

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

lsmd5eda

lsmd5eda1#

哪里出了问题
你做错的地方是

$ 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推断出任何内容是文件或目录。

h43kikqp

h43kikqp2#

一种方法是手动创建.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

应用更改

5cnsuln7

5cnsuln73#

git submodule add会检测submosule的路径是否存在,是否包含初始化的git repo,所以不用担心这个问题。我遇到过类似的问题,所以我写了一个(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
wqnecbli

wqnecbli4#

为现有的存储库增加卡洛斯Answer。它已经包含其URL。您可以简单地

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

wj8zmpe15#

不要使用git add添加子模块,使用git submodule add

git submodule [--quiet] add [<options>] [--] <repository> [<path>]

如果您已经克隆了存储库,只需运行

git submodule add -- "$(git -C ./sub/ remote get-url origin)" ./sub/

NB:相对路径前缀./在这里很重要...除非您指定的是绝对路径。

或者

git submodule add -- ./sub.git ./sub

如果项目使用相对URL。

biswetbf

biswetbf6#

1.从索引foo/bar中删除文件:git rm -f --cached foo/bar

  1. git submodule add https://github.com/octocat/Spoon-Knife.git ./foo/bar
jgzswidk

jgzswidk7#

至少,如果(未来的)子模块没有递归的其他仓库/.git目录,那么下面的代码只是简单地添加了所有这些目录。(我不知道为什么我必须在命令中提供目录作为路径和“repository”,但无论如何...)

for d in $(dirname $(find -mindepth 2 -name .git)) ; do git submodule add -- ./$d/ ./$d/ ; done
disho6za

disho6za8#

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

相关问题