将 git 子模块移动到另一个目录后,它失败并显示错误 'git status --porcelain' failed in submodule

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20991138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-19 09:33:05  来源:igfitidea点击:

After moving git submodule to another directory it fails with error 'git status --porcelain' failed in submodule

gitgit-submodules

提问by jaccus

Initially I had the following (simplified) repo structure:

最初我有以下(简化的)repo 结构:

MyRepo
   external1/MySub (git submodule)
   .gitsubmodules

Where

在哪里

$ cat .gitsubmodules

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

I then wanted to move MySubmodule to another directory in the same git repository, e.g., external2so the structure is as follows:

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

MyRepo
   external2/MySub (git submodule)
   .gitsubmodules


What I did, and thought is enough, I simply moved (via OS mv) the external1/MySubdirectory to external2/MySuband edited the .gitsubmodulesfile to:

我所做的,并且认为已经足够了,我只是将(通过 OS mvexternal1/MySub目录移动到external2/MySub并将.gitsubmodules文件编辑为:

$ cat .gitsubmodules

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

After this change, I get the following error:

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

$ 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


What am I missing? Any other changes need to be done for such move to work?

我错过了什么?是否需要进行任何其他更改才能使此类移动生效?

(I'm using git version 1.8.3rc3 on Windows 8.1)

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

回答by VonC

I simply moved the external1/MySub directory to external2/MySub

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

Move as in mv(unix command), or git mv(git command)?

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

You need to move the special entryof the indexrepresenting the submodule for the parent repo.

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

Normally, (reading git mv), this should have been enough:

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

git mv external1/MySub external2/MySub

Moving a submodule using a gitfile (which means they were cloned with a Git version 1.7.8 or newer) will update the gitfileand core.worktreesetting to make the submodule work in the new location.
It also will attempt to update the submodule.<name>.pathsetting in the gitmodulesfile and stage that file (unless -n is used).

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

That works best with the latest 1.8.5 git (like msysgit for Windows, or latest package for Unix)

这最适合最新的 1.8.5 git(如Windows 的 msysgitUnix 的最新包



Suseikaadds in the comments

Suseika在评论中添加

If you get message

如果你收到消息

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

it is probably because you're adding a directory level, e.g. moving submodule "math" to "libs/math".
git mvdoesn't create missing [intermediate] directories, you should mkdirthem yourself.

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



git 2.9 (June 2016) will improve git mvfor submodule:

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

See commit a127331(19 Apr 2016) by Stefan Beller (stefanbeller).
(Merged by Junio C Hamano -- gitster--in commit 9cb50a3, 29 Apr 2016)

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

mv: allow moving nested submodules

"git mv old new" did not adjust the path for a submodule that lives as a subdirectory inside old/directory correctly.

submodules however need to update their link to the git directory as well as updates to the .gitmodulesfile.

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

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

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



Git 2.12 (Q1 2017) offers to move nested submodules to the parent repo:

Git 2.12(2017 年第一季度)提供了将嵌套子模块移动到父存储库的功能:

There is a new submodule helper "git submodule absorbgitdirs" to make it easier to move embedded .git/directory for submodules in a superproject to .git/modules/(and point the latter with the former that is turned into a "gitdir:" file) has been added.

添加了一个新的子模块助手“ git submodule absorbgitdirs”,可以更轻松地将.git/超级项目中的子模块的嵌入目录移动到.git/modules/(并将后者指向变成“ gitdir:”文件的前者)。

See commit 7c4be45(27 Dec 2016), commit f6f8586, commit 47e83eb, commit 1a248cf(12 Dec 2016), and commit 6f94351, commit 89c8626, commit 90c0011, commit 6f94351, commit 89c8626, commit 90c0011(08 Dec 2016) by Stefan Beller (stefanbeller).
(Merged by Junio C Hamano -- gitster--in commit da2b74e, 10 Jan 2017)

提交7c4be45(2016年12月27日),提交f6f8586提交47e83eb提交1a248cf(2016年12月12日),以及提交6f94351提交89c8626提交90c0011提交6f94351提交89c8626提交90c0011(2016年12月8日)由斯蒂芬贝勒(stefanbeller)
(由Junio C gitsterHamano合并-- --da2b74e 提交中,2017 年 1 月 10 日)

submodule: add absorb-git-dirfunction

When a submodule has its gitdir inside the working dir, the submodule support for checkout that we plan to add in a later patch will fail.

Add functionality to migrate the git directory to be absorbed into the superprojects git directory.

The newly added code in this patch is structured such that other areas of Git can also make use of it. The code in the submodule--helper is a mere wrapper and option parser for the function absorb_git_dir_into_superproject, that takes care of embedding the submodules git directory into the superprojects git dir. That function makes use of the more abstract function for this use case relocate_gitdir, which can be used by e.g. the worktree code eventually to move around a git directory.

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

当子模块的git目录位于工作目录中时,我们计划在以后的补丁中添加的对检出的子模块支持将失败。

添加将 git 目录迁移到 superprojects git 目录中的功能。

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



Note: there is still (Git 2.14.x/2.15, Q4 2017) a bug linked to submodule moving: see "Git: moving submodules recursively (nested submodules)".

注意:仍然存在(Git 2.14.x/2.15,2017 年第四季度)一个与子模块移动相关的错误:请参阅“ Git:递归移动子模块(嵌套子模块)”。



Git 2.15.x/2.16 (Q1 2018) will make moving submodule more robust, since "git fetch --recurse-submodules" now knows that submodules can be moved around in the superproject in addition to getting updated, and finds the ones that need to be fetched accordingly.

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

See commit 4b4aced, commit c68f837(16 Oct 2017), and commit 01ce122(06 Oct 2017) by Heiko Voigt (hvoigt).
(Merged by Junio C Hamano -- gitster--in commit b4d658b, 06 Nov 2017)

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

implement fetching of moved submodules

We store the changed submodules paths to calculate which submodule needs fetching. This does not work for moved submodules since their paths do not stay the same in case of a moved submodules.
In case of new submodules we do not have a path in the current checkout, since they just appeared in this fetch.

It is more general to collect the submodule names for changes instead of their paths to include the above cases. If we do not have a configuration for a gitlink we rely on constructing a default name from the path if a git repository can be found at its path. We skip non-configured gitlinks whose default name collides with a configured one.

实现获取移动的子模块

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

更普遍的是收集子模块名称以进行更改而不是包含上述情况的路径。如果我们没有 gitlink 的配置,如果可以在其路径中找到 git 存储库,我们将依赖于从路径构造默认名称。我们跳过默认名称与已配置名称冲突的未配置 gitlink。



Note that, beforeGit 2.19 (Q3 2018), the code to try seeing if a fetch is necessary in a submodule during a fetch with --recurse-submodulesgot confused when the path to the submodule was changed in the range of commits in the superproject, sometimes showing "(null)".
This has been corrected.

请注意,Git 2.19(2018 年第 3 季度)之前,--recurse-submodules当在超级项目的提交范围内更改子模块的路径时,尝试查看在获取期间是否需要在子模块中进行获取的代码会感到困惑,有时会显示“ (null)”。
这已得到纠正。

See commit c3749f6, commit 5fc8475(14 Jun 2018) by Stefan Beller (stefanbeller).
(Merged by Junio C Hamano -- gitster--in commit 085d2ab, 28 Jun 2018)

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

submodule: fix NULLcorrectness in renamed broken submodules

When fetching with recursing into submodules, the fetch logic inspects the superproject which submodules actually need to be fetched.
This is tricky for submodules that were renamed in the fetched range of commits. This was implemented in c68f837(implement fetching of moved submodules, 2017-10-16, Git v2.16.0), and this patch fixes a mistake in the logic there.

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

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

回答by jaccus

I changed a few more things manually and it actually worked with git 1.8.3rc3 (unnecessary with git 1.8.5):

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

  1. Fix gitdirpath in .git submodule filerepo/external2/MySub/.git:

    -gitdir: ../../../.git/modules/external1/MySub
    +gitdir: ../../../.git/modules/external2/MySub
    
  2. Rename submodule directory under repo/.git/modules/directory

    $ mv repo/.git/modules/external1 repo/.git/modules/external2
    
  3. Fix worktreepath in repo/.git/modules/external2/MySub/config

    -worktree = ../../../../../external1/MySub
    +worktree = ../../../../../external2/MySub
    
  1. 修复gitdir.git 子模块文件中的路径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