重命名一个 git 子模块

230

有没有一种简单的方法来重命名一个 git 子模块目录(而不是经过整个删除并重新添加到新目标名称的流程)。

同时,为什么我不能在父目录中直接执行以下操作:git mv old-submodule-name new-submodule-name


9
当移动子模块时,您将不再需要手动更新.gitmodules。请参见我的下面的答案 - VonC
@VonC的答案对我非常有效。 - laconbass
Git 模块过于复杂。npm 显示了简单易用的方式。也许有一天,会有人重写它... 在此期间... - Rolf
2
@VonC的回答并不是完整的故事,因为现在它确实会更改.gitmodules文件,但只会重命名路径,而不是模块名称。您需要对.gitmodules进行额外的编辑以更正这一点,并使用'git submodule sync'完成整个过程。 - zertyz
@zertyz:属性[submodule "name_of_submodule"]是Git的内部名称,你可以将其重命名以避免混淆,但它只是一个标签。 - MKesper
标题有误导性,应该是“更改git子模块路径”。据我所知,无法重命名子模块。也就是说,“.gitmodules”文件中的“path”和“url”部分可以被操作,但是子模块声明不能被操作。如果你想让模块名称与路径对齐,你必须删除并重新创建。 - Max Robbertze
7个回答

326

Git1.8.5(2013年10月)应该简化该过程。只需执行:

git mv A B

"git mv A B",当移动子模块A时,已经学会了重新定位其工作树并调整.gitmodules文件中的路径

提交 0656781fadca1中查看更多:

目前在子模块上使用“git mv”命令会将子模块的工作树移动到超级项目中。但是,.gitmodules文件中子模块的路径设置保持不变,这与工作树不一致,并使依赖于正确的路径 ->名称映射(如状态和差异)的git命令表现出奇怪的行为。让“git mv”在此处发挥作用,不仅移动子模块的工作树,还更新.gitmodules文件中的“submodule.<submodule name>.path”设置并进行暂存。当没有找到.gitmodules文件时,不会发生这种情况,并且仅在没有此子模块的部分时发出警告。这是因为用户可能只使用纯gitlinks而没有.gitmodules文件,或者已经在发出“git mv”命令之前手动更新了路径设置(在这种情况下,警告提醒他mv本来可以为他完成这项工作)。仅当发现.gitmodules文件并包含合并冲突时,mv命令才会失败,并告诉用户在再次尝试之前解决冲突。

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

请参见commit a127331 (2016年4月19日),作者为Stefan Beller (stefanbeller)
(由Junio C Hamano -- gitster --合并于commit 9cb50a3,2016年4月29日)

mv: 允许移动嵌套子模块

"git mv old new"未正确调整作为old/目录下子目录存在的子模块的路径。

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


2
@MaksimDmitriev 但是关于我在 https://dev59.com/ZGEi5IYBdhLWcg3w4PhB#20918469 中提到的个人软件包存档(PPA),您怎么看? - VonC
这对我来说是全新的,而且将来我一定会用到它。谢谢你的发布! - aendra
2
我的电脑上git mv并不能很好地完成这个目的。 - Alexander Dyagilev
1
@VonC 使用 "git mv currentname newname" 命令时,我遇到了错误 "fatal: cannot move directory over file source=currentname , destination=newname/currentname"。我的 git 版本是 2.23.0.windows.1,在 Windows 10 上通过 git bash 运行。currentname 和 newname 只有首字母大小写不同(例如 Code -> code)。 - feature_engineer
1
@VonC 我已经通过将其重命名为临时名称,然后再改回正确的名称来解决了这个问题 - 我怀疑这是因为这些名称仅在大小写上有所不同,而Windows路径是不区分大小写的。虽然错误消息可能会更有帮助。 - feature_engineer
显示剩余21条评论

121

我发现以下工作流程有效:

  • 更新.gitmodules
  • mv oldpath newpath
  • git rm oldpath
  • git add newpath
  • git submodule sync

注意:这种方法在2018年的GIT版本中不能正确更新索引和.gitmodules文件。

注意:如VonC答案中指出,现在可能只需要执行git mv oldpath newpath即可。(确保您正在使用最新版本的git)


23
备忘录:对于 git add newpath,不要使用尾随斜杠。 - atomicules
10
使用这种工作流程,你只会创建一个符号链接来作为子模块使用的子目录。符号链接只是全局子模块功能的一部分。这意味着当你克隆使用重命名子模块的 repo 时,可能会出现以下错误: *在路径“旧路径”中找不到.gitmodules 中的子模块映射。在删除旧路径 (git rm oldpath) 后,你应该使用 git submodule add REPO-URL newpath 代替 "git add newpath"。 完成后,git status 将显示如下内容: 重命名:oldpath -> newpath - Bertrand
5
这个解决方案对我无效,因为当使用“git add”命令时,子模块被包含到项目中作为一个简单的目录而不是子模块。尝试以下步骤: $ mv 子模块旧路径 ~/另一个位置 $ git rm 子模块旧路径 $ git submodule add 子模块仓库URL 子模块新路径参考链接:http://bcachet.github.io/development/2012/05/25/rename-git-submodule/ - Mahmoud Adam
3
如果您的工作树存在问题,您也可以编辑 .git/modules/SUBMODULE/config 文件,以便 worktree 再次指向正确的目录。 - Vincent Ketelaars
5
对于我的git版本2.13.1,这并没有起作用。但是简单地使用git mv old new非常有效。我只需要执行git commit来完成更改。 - user
显示剩余7条评论

19

正确的解决方案是:

mv oldpath ~/another-location
git rm oldpath
git submodule add submodule-repository-URL newpath

4
你是不是直接从这个位置逐字拷贝的?http://bcachet.github.io/development/2012/05/25/rename-git-submodule/ 如果是的话,请确保在你的回答中给予该网站归属权。 - George Stocker
链接已损坏。 - Alexis Wilke

14

无法更改名称,因此您需要首先将其删除 (deinit),然后再添加它。

因此,在删除它之后:

git submodule deinit <path>
git rm --cached <path>

你可能还需要仔细检查并移除以下位置对它的引用:

  • .gitmodules
  • .git/config
  • .git/modules/<name>中删除引用文件夹(最好备份一下),因为每个文件夹都有一个config文件,其中保存了对其worktree的引用。

然后通过将更改提交到存储库来提交您的更改:

git commit -am 'Removing submodule.'

并且请再次检查,确保您没有任何未解决的问题:

git submodule update
git submodule sync
git submodule status

现在,您可以再次添加git子模块:

git submodule add --name <custom_name> git@github.com:foo/bar.git <my/path>

今天就是今天,也确实是。 - Alexey
3
问题的标题是一个误称,它涉及到路径而不是名称。 - Max Robbertze

12

我刚刚尝试了上面建议的一些方法。我的系统环境是:

$ git --version
git version 1.8.4

我发现最好的方法是取消初始化子模块,删除该目录并创建一个新的子模块。

git submodule deinit <submodule name>

git rm <submodule folder name>

git submodule add <address to remote git repo> <new folder name>

至少对我来说是这样最有效的,但你的经验可能不同!


5

MacOS:当我想要使用VonC解决方案将子模块文件夹Common更改为小写字母时:

git mv Common common

我理解你遇到了问题,错误信息是“fatal: renaming 'Common' failed: Invalid argument”。

解决方案 - 使用一些临时文件夹名称并进行两次移动:

git mv Common commontemp
git mv commontemp common

That's all :)


4

编辑.gitmodules文件以重命名子模块,然后重命名子模块目录。

我认为你可能需要在此之后执行git submodule sync,但我现在无法检查。


这会导致新的子模块名称出现为一个新的提交,而不是重命名。但也许这就是必须的方式? - Lars Tackmann
1
@Lars:一定要记得删除旧的子模块目录! - Cascabel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接