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

jac*_*cus 21 git git-submodules

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

MyRepo
   external1/MySub (git submodule)
   .gitsubmodules
Run Code Online (Sandbox Code Playgroud)

哪里

$ cat .gitsubmodules

  [submodule "external1/MySub"]
  path = external1/MySub
  url = user@repo:/remoterepo/externals/MySub.git
Run Code Online (Sandbox Code Playgroud)

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

MyRepo
   external2/MySub (git submodule)
   .gitsubmodules
Run Code Online (Sandbox Code Playgroud)

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

$ cat .gitsubmodules

  [submodule "external2/MySub"]
  path = external2/MySub
  url = user@repo:/remoterepo/externals/MySub.git
Run Code Online (Sandbox Code Playgroud)

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

$ 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
Run Code Online (Sandbox Code Playgroud)

我错过了什么?这种搬迁需要做出任何其他改变吗?

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

Von*_*onC 28

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

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

你需要移动的特殊项指数代表父回购的子模块.

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

git mv external1/MySub external2/MySub
Run Code Online (Sandbox Code Playgroud)

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

最适合最新的1.8.5 git(如msysgit for Windows,或最新的Unix包)


Suseika 在评论中补充道

如果你得到消息

fatal: renaming '%submodule%' failed: No such file or directory
Run Code Online (Sandbox Code Playgroud)

这可能是因为您正在添加目录级别,例如将子模块" math" 移动到" libs/math".
git mv不会创建丢失的[中间]目录,你mkdir自己应该这样做.


git 2.9(2016年6月)将改进git mv子模块:

请参阅Stefan Beller()提交a127331(2016年4月19日).(由Junio C Hamano合并- -提交9cb50a3,2016年4月29日)stefanbeller
gitster

mv:允许移动嵌套的子模块

" git mv old new"没有正确调整作为目录内部子目录的子模块的路径old/.

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


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

有一个新的子模块助手" git submodule absorbgitdirs",可以更容易地将.git/超级项目中的子模块的嵌入式目录移动到.git/modules/(并指向后者,并将前者转换为" gitdir:"文件).

请参阅提交7c4be45(2016年12月27日),提交f6f8586,提交47e83eb,提交1a248cf(2016年12月12日),提交6f94351,提交89c8626,提交90c0011,提交6f94351,提交89c8626,提交90c0011(2016年12月8日)作者:Stefan Beller(stefanbeller).
(由Junio C gitsterHamano合并- -提交da2b74e,2017年1月10日)

子模块:添加absorb-git-dir功能

当子模块的gitdir位于工作目录内时,我们计划在稍后的补丁中添加的子模块支持结帐将失败.

添加功能以迁移git目录以吸收到superprojects git目录中.

此补丁中新添加的代码的结构使得Git的其他区域也可以使用它.子模块中的代码--helper只是该函数的absorb_git_dir_into_superproject包装器和选项解析器,它负责将子模块git目录嵌入到superprojects git目录中.该函数利用了这个用例relocate_gitdir更抽象的函数, 例如,工作树代码最终可以在git目录中移动.


注意:仍然存在(Git 2.14.x/2.15,Q4 2017)与子模块移动相关的错误:请参阅" Git:递归移动子模块(嵌套子模块) ".


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

请参阅提交4b4aced,提交c68f837(2017年10月16日),并由Heiko Voigt()提交01ce122(2017年10月6日).(由Junio C Hamano合并- -提交b4d658b,2017年11月6日)hvoigt
gitster

实现获取移动的子模块

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

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


请注意, Git 2.19(Q20 2018)之前,--recurse-submodules在超级项目的提交范围内,当子模块的路径发生变化时,尝试查看在提取期间子模块中是否需要提取的代码变得困惑,有时显示" (null)".
这已得到纠正.

请参阅Stefan Beller()提交c3749f6,提交5fc8475(2018年6月14日).(由Junio C Hamano合并- -提交085d2ab,2018年6月28日)stefanbeller
gitster

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

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

  • 如果你收到消息"致命:重命名'%submodule%'失败:没有这样的文件或目录",这可能是因为你正在添加一个目录级别,例如将子模块"math"移动到"libs/math".`git mv`不会创建丢失的目录,你应该自己`mkdir`. (2认同)

jac*_*cus 15

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

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

    -gitdir: ../../../.git/modules/external1/MySub
    +gitdir: ../../../.git/modules/external2/MySub
    
    Run Code Online (Sandbox Code Playgroud)
  2. 重命名目录下的子模块repo/.git/modules/目录

    $ mv repo/.git/modules/external1 repo/.git/modules/external2
    
    Run Code Online (Sandbox Code Playgroud)
  3. 修复worktree路径repo/.git/modules/external2/MySub/config

    -worktree = ../../../../../external1/MySub
    +worktree = ../../../../../external2/MySub
    
    Run Code Online (Sandbox Code Playgroud)