如何在Git存储库中移动现有的Git子模块?

时间:2011-01-05 13:24:29

标签: git git-submodules

我想在我的Git超级项目中更改Git子模块的目录名。

假设我的.gitmodules文件中有以下条目:

[submodule ".emacs.d/vimpulse"]  
path = .emacs.d/vimpulse  
url = git://gitorious.org/vimpulse/vimpulse.git

我必须键入什么来将.emacs.d/vimpulse目录移动到.emacs.d/vendor/vimpulse而不先删除它(解释   herehere),然后重新添加。

Git是否真的需要子模块标记中的整个路径

[submodule ".emacs.d/vimpulse"]

或者是否也可以只存储子项目的名称?

[submodule "vimpulse"]

9 个答案:

答案 0 :(得分:306)

注意:如评论中所述,此答案涉及旧版git所需的步骤。 Git现在支持移动子模块:

  

从git 1.8.5开始,git mv old/submod new/submod按预期工作,并为您完成所有管道工作。您可能希望使用git 1.9.3或更新版本,因为它包含子模块移动的修复程序。


它与删除子模块的方式类似(参见How do I remove a submodule?):

  1. 修改.gitmodules并相应地更改子模块的路径,并将其放在带有git add .gitmodules的索引中。
  2. 如果需要,请创建子模块的新位置的父目录(mkdir -p new/parent)。
  3. 将所有内容从旧目录移至新目录(mv -vi old/parent/submodule new/parent/submodule)。
  4. 确保Git跟踪此目录(git add new/parent)。
  5. 使用git rm --cached old/parent/submodule删除旧目录。
  6. 将目录.git/modules/old/parent/submodule的所有内容移至.git/modules/new/parent/submodule
  7. 修改.git/modules/new/parent/config文件,确保worktree项指向新位置,因此在此示例中应为worktree = ../../../../../new/parent/module。通常,在该位置的直接路径中应该还有两个..目录。
  8. 编辑文件new/parent/module/.git,确保其中的路径指向主项目.git文件夹中的正确新位置,因此在此示例中为gitdir: ../../../.git/modules/new/parent/submodule。< / p> 之后

    git status输出对我来说是这样的:

    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       modified:   .gitmodules
    #       renamed:    old/parent/submodule -> new/parent/submodule
    #
    
  9. 最后,提交更改。

答案 1 :(得分:205)

最现代的答案,取自上面的Valloric评论:

  1. 升级到Git 1.9.3(或2.18 if the submodule contains nested submodules
  2. git mv old/submod new/submod
  3. 之后.gitmodules和子模块目录已经暂存进行提交(您可以使用git status进行验证。)
  4. 使用git commit提交更改,您就可以了!
  5. 完成!

答案 2 :(得分:55)

就我而言,我想将子模块从一个目录移动到子目录中,例如“AFNetworking” - &gt; “EXT / AFNetworking”。这些是我遵循的步骤:

  1. 编辑.gitmodules将子模块名称和路径更改为“ext / AFNetworking”
  2. 将子模块的git目录从“.git / modules / AFNetworking”移动到“.git / modules / ext / AFNetworking”
  3. 将库从“AFNetworking”移至“ext / AFNetworking”
  4. 编辑“.git / modules / ext / AFNetworking / config”并修复[core] worktree行。我的从../../../AFNetworking更改为../../../../ext/AFNetworking
  5. 修改“ext / AFNetworking / .git”并修复gitdir。我的从../.git/modules/AFNetworking更改为../../git/modules/ext/AFNetworking
  6. git add .gitmodules
  7. git rm --cached AFNetworking
  8. git submodule add -f <url> ext/AFNetworking
  9. 最后,我在git状态中看到了:

    matt$ git status
    # On branch ios-master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #   modified:   .gitmodules
    #   renamed:    AFNetworking -> ext/AFNetworking
    

    Et瞧。上面的例子不会改变目录深度,这会对任务的复杂性产生很大的影响,并且不会改变子模块的名称(这可能不是必需的,但我这样做是为了与如果我在那条路径上添加了一个新模块,就会发生这种情况。)

答案 3 :(得分:18)

[更新:2014-11-26]正如Yar总结如下,在您做任何事情之前,请确保您知道子模块的网址。如果未知,打开.git/.gitmodules并检查密钥submodule.<name>.url

对我来说有用的是remove the old submodule使用git submodule deinit <submodule>后跟git rm <submodule-folder>。然后使用新文件夹名称和提交再次添加子模块。在提交之前检查git状态显示旧的子模块重命名为新名称并且.gitmodule已修改。

$ git submodule deinit foo
$ git rm foo
$ git submodule add https://bar.com/foo.git new-foo
$ git status
renamed:    foo -> new-foo
modified:   .gitmodules
$ git commit -am "rename foo submodule to new-foo"

答案 4 :(得分:11)

诀窍似乎是要了解子模块的.git目录现在保存在主.git/modules下的主存储库中,并且每个子模块都有一个指向它的.git文件。这是您现在需要的程序:

  • 将子模块移动到新家。
  • 编辑子模块工作目录中的.git文件,并修改其包含的路径,使其指向主存储库.git/modules目录中的正确目录。
  • 输入主存储库的.git/modules目录,找到与子模块对应的目录。
  • 编辑config文件,更新worktree路径,使其指向子模块工作目录的新位置。
  • 编辑主存储库根目录中的.gitmodules文件,更新子模块工作目录的路径。
  • git add -u
  • git add <parent-of-new-submodule-directory>(重要的是添加,而不是子模块目录本身。)

一些注意事项:

  • [submodule "submodule-name"].gitmodules中的.git/config行必须相互匹配,但与其他内容不对应。
  • 子模块工作目录和.git目录必须正确指向对方。
  • 应同步.gitmodules.git/config个文件。

答案 5 :(得分:8)

“[submodule”]之后引号中的字符串无关紧要。如果需要,您可以将其更改为“foobar”。它用于在“.git / config”中找到匹配的条目。

因此,如果在运行“git submodule init”之前进行更改,它将正常工作。如果您进行更改(或通过合并获取更改),则需要手动编辑.git / config或再次运行“git submodule init”。如果你做了后者,你将留下一个无害的“搁浅”条目,旧名称在.git / config中。

答案 6 :(得分:2)

给定的解决方案对我不起作用,但类似的版本确实......

这是一个克隆的存储库,因此子模块git repos包含在顶级存储库.git目录中。所有阳离子都来自顶级存储库:

  1. 编辑.gitmodules并更改相关子模块的“path =”设置。 (无需更改标签,也无需将此文件添加到索引中。)

  2. 编辑.git / modules / name / config并更改有问题的子模块的“worktree =”设置

  3. 运行:

    mv submodule newpath/submodule
    git add -u
    git add newpath/submodule
    
  4. 我想知道如果存储库是原子的,或者相对的子模块是否有所不同,在我的情况下它是相对的(子模块/ .git是ref to to to to to to to to to to to to to to to to to to to to to to to to

答案 7 :(得分:2)

只需使用shell脚本git-submodule-move

答案 8 :(得分:2)

我昨天刚经历了这场考验,this answer完美无缺。为清晰起见,以下是我的步骤:

  1. 确保已签入子模块并将其推送到其服务器。你还需要知道它的分支。
  2. 您需要子模块的网址!使用more .gitmodules,因为一旦删除了子模块,它就不会出现在
  3. 现在,您可以使用deinitrm,然后使用submodule add
  4. 示例

    <强>命令

        git submodule deinit Classes/lib/mustIReally
        git rm foo
        git submodule add http://developer.audiob.us/download/SDK.git lib/AudioBus
    
        # do your normal commit and push
        git commit -a 
    

    注意: git mv不会这样做。完全没有。