将git子模块移动到另一个目录后,它失败,并且子模块中出现错误'git status --porcelain'失败

时间:2014-01-08 09:07:32

标签: git git-submodules

最初我有以下(简化)回购结构:

MyRepo
   external1/MySub (git submodule)
   .gitsubmodules

其中

$ cat .gitsubmodules

  [submodule "external1/MySub"]
  path = external1/MySub
  url = user@repo:/remoterepo/externals/MySub.git

然后我想将MySubmodule移动到同一个git存储库中的另一个目录,例如 external2 ,所以结构如下:

MyRepo
   external2/MySub (git submodule)
   .gitsubmodules

我做了什么,并且已经足够了,我只是将 external1 / MySub 目录移动(通过操作系统mv)到 external2 / MySub 并编辑了 .gitsubmodules 文件:

$ cat .gitsubmodules

  [submodule "external2/MySub"]
  path = external2/MySub
  url = user@repo:/remoterepo/externals/MySub.git

在此更改后,我收到以下错误:

$ git status

  fatal: Could not chdir to '../../../../../repo/external/MySub': No such file or directory
  fatal: 'git status --porcelain' failed in submodule repo/external2/MySub

我错过了什么?是否需要进行任何其他更改以使此类移动起作用?

(我在Windows 8.1上使用git版本1.8.3rc3)

2 个答案:

答案 0 :(得分:28)

  

我只是将external1 / MySub目录移动到external2 / MySub

mv(unix命令)或git mv(git命令)移动?

您需要移动代表父代表的子模块的special entry the index

通常,(阅读git mv),这应该足够了:

git mv external1/MySub external2/MySub
  

使用gitfile移动子模块(这意味着它们是使用Git 1.7.8或更高版本克隆的)将更新gitfilecore.worktree设置以使子模块在新位置工作。
  它还将尝试更新submodule.<name>.path文件中的gitmodules设置并暂存该文件(除非使用-n)。

最适合最新的1.8.5 git(如msysgit for Windowslatest package for Unix


Suseika添加in the comments

  

如果收到消息

fatal: renaming '%submodule%' failed: No such file or directory
  

可能是因为您正在添加目录级别,例如移动子模块&#34; math&#34;到&#34; libs/math&#34;。
  git mv没有创建丢失的[中间]目录,您应该自己mkdir


git 2。9(2016年6月)将改进子模块的git mv

commit a127331Stefan Beller (stefanbeller)(2016年4月19日) (由Junio C Hamano -- gitster --合并于commit 9cb50a3,2016年4月29日)

  

mv:允许移动嵌套子模块

     

&#34; git mv old new&#34;没有正确调整作为old/目录中子目录的子模块的路径。

     然而,

子模块需要更新它们到git目录的链接   以及.gitmodules文件的更新。


Git 2.12(2017年第1季度)提供将嵌套子模块移动到父级仓库:

有一个新的子模块助手&#34; git submodule absorbgitdirs &#34;为了更容易移动嵌入式.git/目录中的子模块 超级项目.git/modules/(并指出后者与前者 这变成了&#34; gitdir:&#34;文件)已被添加。

请参阅commit 7c4be45(2016年12月27日),commit f6f8586commit 47e83ebcommit 1a248cf(2016年12月12日)和commit 6f94351commit 89c8626commit 90c0011commit 6f94351commit 89c8626commit 90c0011(2016年12月8日)Stefan Beller (stefanbeller)
Junio C Hamano -- gitster --于2017年1月10日commit da2b74e合并)

  

子模块:添加absorb-git-dir函数

     

当子模块在工作目录,子模块中有git目录时   我们计划在以后的补丁中添加的结帐支持将失败。

     

添加迁移git目录以吸收的功能   进入superprojects git目录。

     

此补丁中新添加的代码的结构使得其他区域   Git也可以使用它。子模块中的代码 - 帮助器仅仅是一个   function absorb_git_dir_into_superproject的包装器和选项解析器,负责嵌入   子模块git目录进入superprojects git dir。那个功能   使用more abstract function for this use case relocate_gitdir,可以使用例如Git: moving submodules recursively (nested submodules)。最终的工作树代码   移动一个git目录。


注意:仍存在(Git 2.14.x / 2.15,2017年第4季度)与子模块移动相关的错误:请参阅&#34; commit 4b4aced&#34;。


Git 2.15.x / 2.16(2018年第一季度)将使移动子模块更加健壮,因为&#34; git fetch --recurse-submodules&#34;现在知道子模块可以 除了获得更新之外,在超级项目中移动, 并找到需要相应提取的那些。

commit c68f837commit 01ce122(2017年10月16日)和Heiko Voigt (hvoigt)(2017年10月6日)Junio C Hamano -- gitster --commit b4d658b合并于commit c3749f6,2017年11月6日)

  

实现获取移动的子模块

     

我们存储已更改的子模块路径以计算哪个子模块需要   取。这对于移动的子模块不起作用,因为它们的路径可以   如果移动子模块,则不能保持不变   在新子模块的情况下,我们在当前结帐时没有路径,因为它们刚出现在此获取中。

     

更常见的是收集更改的子模块名称而不是   他们的路径包括上述案例。如果我们没有   我们依赖于构建默认名称的gitlink配置   如果可以在其路径中找到git存储库的路径。我们跳过   未配置的gitlinks,其默认名称与已配置的名称冲突   之一。


请注意,在 Git 2.19(Q3 2018)之前的,在使用--recurse-submodules获取期间尝试查看子模块中是否需要获取的代码在路径到子模块在提交范围内发生了变化 超级项目,有时显示&#34; (null)&#34;。
这已经得到纠正。

commit 5fc8475Stefan Beller (stefanbeller)Junio C Hamano -- gitster --(2018年6月14日) (由commit 085d2ab合并于c68f837,2018年6月28日)

  

submodule:在重命名的已损坏的子模块中修复NULL正确性

     

当通过递归到子模块获取时,获取逻辑会检查   超级项目实际上需要获取哪些子模块   对于在提取的提交范围内重命名的子模块,这很棘手。   这是在{{3}}中实现的(实现了移动的提取   子模块,2017-10-16,Git v2.16.0),这个补丁修复了逻辑中的错误   那里。

答案 1 :(得分:15)

我手动改变了一些东西,它实际上与git 1.8.3rc3一起使用(git 1.8.5不需要):

  1. 修复.git子模块中的gitdir路径文件 repo/external2/MySub/.git

    -gitdir: ../../../.git/modules/external1/MySub
    +gitdir: ../../../.git/modules/external2/MySub
    
  2. 重命名repo/.git/modules/目录

    下的子模块目录
    $ mv repo/.git/modules/external1 repo/.git/modules/external2
    
  3. 修复worktree

    中的repo/.git/modules/external2/MySub/config路径
    -worktree = ../../../../../external1/MySub
    +worktree = ../../../../../external2/MySub