如何将GIT仓库转换为子模块,该子模块嵌套在另一个(父)GIT仓库中?

时间:2015-02-03 19:06:34

标签: git version-control repository git-submodules git-extensions

我有一个GIT仓库,其子目录为GIT子仓库。

+ main (local GIT repo)
  + subdirectory1
     + plugin1 (created as local GIT repo)
     + plugin2 (created as local GIT repo)
  + subdirectory2
    + subdirectory2a
      + plugin3 (created as local GIT repo)
  + subdirectory3

plugin1,plugin2,plugin3是主GIT仓库的子文件夹(子目录)。 plugin1,plugin2,plugin3也作为本地GIT repos启动,并且具有内容&历史补充。

我想将plugin1,plugin2,plugin3 GIT子目录转换为子模块或主GIT仓库。

我想在插件GIT repos中单独进行开发,但仍保留为子文件夹,也仍然显示为主GIT仓库中的链接。 我使用GIT Extensions作为开发版本控制GUI。

4 个答案:

答案 0 :(得分:3)

切换到 main 目录,签出master分支,然后执行以下Git命令为plugin1创建一个新的子模块:

git submodule add (url_to_plugin1_repository) subdirectory1/plugin1sm

此处“url_to_plugin1_repository”指向 plugin1 的当前Git存储库。将创建一个名为 subdirectory1 / plugin1sm 的新目录,该目录将跟踪您的远程存储库。我给它一个不同的名称,以区别于不是子模块的 plugin1 目录。请注意,Git将从远程URL克隆 plugin1sm 目录的数据,而不是仅从本地复制。话虽这么说,如果您在本地 plugin1 存储库中有任何未经修改的更改,您应该在执行上述步骤之前提交并推送它们。

此时,从目录中执行git状态应显示类似于以下内容的内容:

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD ..." to unstage)
#
#   new file:   .gitmodules
#   new file:   subdirectory1/plugin1sm

由于您位于目录中,因此新子模块在变更集中显示为“文件”。您可以使用以下命令提交此更改:

$ git add subdirectory1/plugin1sm
$ git commit -m "Created submodule for plugin1"
$ git push origin master

您可能会想到的下一个问题是如何使用新的子模块以及您的主Git存储库。让我们首先看一下处理 plugin1sm 目录中的文件时会发生什么。当您在 plugin1sm 目录中工作时,Git将跟踪更改并表现得好像它不知道该目录之外的任何内容。当提交并推送您的更改时,您可以使用以下预期命令:

$ cd subdirectory1/plugin1sm
$ git add <yourfile>
$ git commit -m "modified my file"
$ git push

但主存储库怎么样?这是事情变得有趣的地方。由于您修改了 plugin1sm 子模块,因此它将在主存储库的变更集中显示为已修改的“文件”。要继续,您可以添加子模块并使用以下命令推送它:

$ cd ../../
$ git add subdirectory1/plugin1sm
$ git commit -m "updated my submodule"
$ git push origin master</code>

总而言之,子模块中的基本Git工作流程将照常运行,并且在存储库中,您需要记住整个子模块将显示为文件。事情变得比我们在这里考虑的简单用例更复杂,但希望这会让你走上正确的道路。

您可以对 plugin2 plugin3 目录重复此过程。当您完成子模块的创建后,您应该能够删除原始插件目录。

答案 1 :(得分:1)

这个解决方案最终似乎对我有用(在Windows下,使用Git Extensions作为用户界面):

以下操作在命令行中完成:

cd c:\!GIT\main     # main
git branch
git checkout dev-main

mkdir subdirectory1\plugin1
cd subdirectory1/plugin1
git init        # init git
git status      # show status
git add .       # stage
git commit -m "Initial commit"      # initial commit
git checkout -b "dev"       # create dev branch
git remote add origin ./subdirectory1/plugin1    # add remote path

# create submodule in main
cd ../..
git submodule add ./subdirectory1/plugin1 subdirectory1/plugin1  # create submodule
git submodule   # show submodules
git status
git add .       # stage submodule
git status
git commit -m "Submodule subdirectory1/plugin1"
git status
git config submodule.subdirectory1/plugin1.url ./subdirectory1/plugin1   # add relative path to config
git submodule   # show submodules

答案 2 :(得分:1)

我的回答有两部分,条件和解决方案。

第一部分:条件

我有同样的问题,但我已经有一个类似的存储库具有相同的结构, 说

Project1 (not a repo)
   |___ Repo1
   |___ Repo2

Project2 (a repo)
   |___ Submodule1 (same repo as Repo1)
   |___ Submodule2 (same repo as Repo2)

我想将Repo1和Repo2转换为Project1的子模块,它与Project2基本相同。 要明确说明,克隆Project2不会有效,因为Project1和Project2中有更多的文件不一样,但为了简单起见......

所以我的Project1&#39; .git/config看起来像这样

[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true

我的Project2&#39; .git/config是这样的:

[core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
[submodule]
    active = .
[remote "origin"]
    url = ######
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
[submodule "Submodule2"]
    url = ######
[submodule "Subodule2"]
    url = ######

在Project2中,有一个名为.gitmodules的文件:

我有同样的问题,但我已经有一个类似的存储库具有相同的结构, 说

Project1 (not a repo)
   |___ Repo1
   |___ Repo2

Project2 (a repo)
   |___ Submodule1 (same repo as Repo1)
   |___ Submodule2 (same repo as Repo2)

我想将Repo1和Repo2转换为Project1的子模块,它与Project2基本相同。 要明确说明,克隆Project2不会有效,因为Project1和Project2中有更多的文件不一样,但为了简单起见......

所以我的Project1&#39; .git/config看起来像这样:

[core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true

我的Project2&#39; .git/config是这样的:

[core]
    repositoryformatversion = 0
    filemode = false
    bare = false
    logallrefupdates = true
    symlinks = false
    ignorecase = true
[submodule]
    active = .
[remote "origin"]
    url = URL/TO/Project2
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master
[submodule "Path/To/Submodule2"]
    url = ######
[submodule "Path/To/Subodule2"]
    url = ######

在Project2中,有一个名为.gitmodules的文件:

[submodule "Path/To/Submodule1"]
    path = Path/To/Submodule1
    url = ######
    branch = master
[submodule "Path/To/Submodule2"]
    path = Path/To/Submodule2
    url = ######
    branch = master

那该怎么做:

第二部分:解决方案

  1. 确保子模块具有相同的文件夹名称
  2. Project1 (not a repo) |___ Submodule1 |___ Submodule2

    1. 然后将Project2/.gitmodules复制到Project1/

    2. 然后将Projec2 .git/conif的内容子模块部分复制到Project1&#39; .git/config,它基本上看起来像Project2,但不会覆盖[remote&#34;原点&#34;]:

    3. 我的Project1&#39; .git/config是这样的:

      [core]
          repositoryformatversion = 0
          filemode = false
          bare = false
          logallrefupdates = true
          symlinks = false
          ignorecase = true
      [submodule]
          active = .
      [remote "origin"]
          *url = URL/TO/Project1*
          fetch = +refs/heads/*:refs/remotes/origin/*
      [branch "master"]
          remote = origin
          merge = refs/heads/master
      [submodule "Path/To/Submodule2"]
          url = ######
      [submodule "Path/To/Subodule2"]
          url = ######
      

答案 3 :(得分:0)

我做了一个丑陋的黑客来解决我在Git Extensions中的子模块问题 也许不是真的有效,但目前有效。

cd main/subdirectory1/plugin2
git init
git status
git add .
git commit -m "Initial commit of Submodule."
git checkout -b dev     # create branch dev

git submodule add ./subdirectory1/plugin2 subdirectory1/plugin2

Add the following config text to w:/path/to/main/.git/config:
[submodule "subdirectory1/plugin2"]
    url = w:/path/to/main/subdirectory1/plugin2

Add the following config text to w:/path/to/main/.gitmodules (supporting Git Extensions to see submodule):
[submodule "subdirectory1/plugin2"]
    path = subdirectory1/plugin2
    url = w:/path/to/main/subdirectory1/plugin2
    branch = dev