如何在本地更改 git 个子模块 url?

How to change git submodules url locally?

原始 .gitmodules 文件使用硬编码 https url,但对于一些自动化测试,我从 ssh 克隆并使子模块 url 相对于 ../ModuleName。我也不想将这些更改推回到回购协议中。

# change the https://github.com/ with git@github.com:
sed -i 's/https:\/\/github.com\//git@github.com:/g' ".git/config"
# delete the url lines from the submodule blocks of .git/config
sed -i '/submodule/ {$!N;d;}' ".git/config"
# change hardcoded https:// urls of submodules to relative ones
sed -i 's/https:\/\/github.com\/ProjName/../g' ".gitmodules"
# also make the same change in the .git/modules/*/config
sed -i 's/https:\/\/github.com\/ProjName/../g' .git/modules/*/config
# sync and update
git submodule sync
git submodule update --init --recursive --remote

上面的代码片段可以满足我的要求。然而,烦人的是,.git/modules/ 文件夹似乎不受版本控制,但如果我只是删除它,git submodule sync 和大多数其他 Git 操作就会停止工作。

有没有办法在修改 .gitmodules.git/config 文件后重新生成 .git/modules

如果你只想修改用于本地仓库的子模块的 URL,那么不要修改 .gitmodules 文件,那只是为了你想要推送的更改。

相反,首先初始化本地子模块配置:

git submodule init

然后像往常一样修改.git/config文件来更改子模块URL。 (同样,这里不需要修改 .gitmodules,如果这是一个新的克隆,你可能还没有 .git/modules。)

@jthill points out一样,更简单的修改子模块URLs的方法是:

git config submodule.moduleName.url ssh://user@server/path

此时你不想 运行 git submodule sync,因为那会覆盖你刚刚用 .gitmodules 文件。相反,直接前往:

git submodule update --recursive --remote

我尝试了上述解决方案,但由于某种原因出现了一堆问题。以下是备选方案。

在新的存储库中:

  1. git submodule init
  2. 使用git clone ../local/path/to/submodule.git path/in/repo/submodule
  3. 手动初始化每个子模块

每当根存储库子模块散列更改并且您需要同步子模块时:

  1. 更新根存储库
  2. git submodule update 可能还有 --force--recursive 以备不时之需

您不仅可以将子模块 URL 更改为 git config submodule.moduleName.url,而且:

  • 使用 Git 2.25(2020 年第一季度),您可以修改它。
    请参阅“”和新命令 git submodule set-url [--] <path> <newurl>

  • with Git 2.22 (Q2 2019), 你也可以 unset 它:

参见 commit b57e811, commit c89c494 (08 Feb 2019), and commit 7a4bb55 (07 Feb 2019) by Denton Liu (Denton-L)
(由 Junio C Hamano -- gitster -- in commit 01f8d78 合并,2019 年 4 月 25 日)

submodule--helper: teach config subcommand --unset

This teaches submodule--helper config the --unset option, which removes the specified configuration key from the .gitmodule file.

即:

git submodule--helper config --unset submodule.submodule.url &&
git submodule--helper config submodule.submodule.url >actual &&
test_must_be_empty actual

在 Git 2.27(2020 年第 2 季度)中,继续用 C 重写“git submodule”的各个部分,包括 set-url.

参见 commit 6417cf9 (08 May 2020) by Shourya Shukla (periperidip)
(由 Junio C Hamano -- gitster -- in commit 9e8ed17 合并,2020 年 5 月 13 日)

submodule: port subcommand 'set-url' from shell to C

Signed-off-by: Shourya Shukla

Convert submodule subcommand 'set-url' to a builtin. Port 'set-url' to 'submodule--helper.c' and call the latter via 'git submodule.sh'.

我相信这种方法比公认的答案更有优势:

$ git submodule set-url moduleName ssh://user@server/path
$ git restore .gitmodules  # or: git reset HEAD .gitmodules

这将更改所有地方的 URL,然后在您不想更改的地方 (.gitmodules) 将其设置回以前的值。

为什么这比接受的答案更好:当使用 git config submodule.moduleName.url 设置 URL 时,用于将此更改传播到实际子模块签出的命令是 git submodule update --remote。但是,更新 URL 只是该命令的副作用,它的主要用途是(可能)检查子模块中的不同提交。另一方面,set-url 只会按照罐头上说的去做。

我已经尝试按照上述修改配置文件,但是运行遇到了一个新问题: 现在,我得到的不是错误的 URL 和致命错误: “致命:无法获取子模块 'xxx\xxxxx\xxx' 的存储库句柄”。 仅仅更改 URL 似乎将问题推向了其他地方,程序仍然无法到达我想要的子模块。