移动Git子模块时,如何使用子模块的新URL更新父存储库中的完整历史记录?

移动Git子模块时,如何使用子模块的新URL更新父存储库中的完整历史记录?,git,github,git-submodules,git-history,git-history-rewrite,Git,Github,Git Submodules,Git History,Git History Rewrite,谁能帮帮我吗。 我想将一些Git存储库从一台服务器移动到另一台服务器,同时重命名它们。 我遇到的问题是,某些存储库是其他存储库的子模块。我想在顶级模块中所有分支的历史记录中替换子模块的URL,以便在删除原始分支后,我仍然可以返回并重建旧的提交。 我在Windows PC上,目前正在使用.bat文件运行存储库迁移 要将子模块从server1移动到server2,并将名称从sub_old更改为sub_new,我将原始(裸)克隆到C:驱动器上的文件夹中,更改URL,然后向上推到新服务器: git cl

谁能帮帮我吗。 我想将一些Git存储库从一台服务器移动到另一台服务器,同时重命名它们。 我遇到的问题是,某些存储库是其他存储库的子模块。我想在顶级模块中所有分支的历史记录中替换子模块的URL,以便在删除原始分支后,我仍然可以返回并重建旧的提交。 我在Windows PC上,目前正在使用.bat文件运行存储库迁移

要将子模块从server1移动到server2,并将名称从sub_old更改为sub_new,我将原始(裸)克隆到C:驱动器上的文件夹中,更改URL,然后向上推到新服务器:

git clone --bare https://server1/sub_old.git c:\temp_repo
cd c:\temp_repo
git remote set-url origin https://server2/sub_new.git
git push --mirror
git clone --bare https://server1/top_old.git c:\temp_repo
cd c:\temp_repo
git remote set-url origin https://server2/top_new.git
REM At this point I want to change all of the references to the submodule from https://server1/sub_old.git to https://server2/sub_new.git
git push --mirror
然后从server1中删除sub_old

现在,当我想将顶级回购(使用子旧回购作为子模块)移动到新服务器时:

git clone --bare https://server1/sub_old.git c:\temp_repo
cd c:\temp_repo
git remote set-url origin https://server2/sub_new.git
git push --mirror
git clone --bare https://server1/top_old.git c:\temp_repo
cd c:\temp_repo
git remote set-url origin https://server2/top_new.git
REM At this point I want to change all of the references to the submodule from https://server1/sub_old.git to https://server2/sub_new.git
git push --mirror
然后从server1中删除top_old

在我想要更改子模块的所有URL引用时,我尝试使用:

git config --global url.https://server2/sub_new.git.insteadOf https://server1/sub_old.git
但是没有成功。 很明显,我不明白这是怎么回事,也不知道这是否是正确的使用方法

我想在所有分支的历史记录中替换子模块的URL

这需要使用
git过滤器分支
或。从技术上讲,不可能更改任何提交,因此这些命令不能做到这一点。相反,它们将现有存储库的提交复制到包含备用历史记录的一组全新的提交中。1

如果你选择这样做,一定要非常确定你想这样做,因为没有回头路了。考虑使用新的<代码> Git过滤器RPO <代码>,这在这类事情上是更好的。2记住,一旦你完成了,任何人都不应该再使用旧的存储库或它的任何克隆。把那些克隆人赶出去。改为创建新存储库的新克隆

有时,使用git-config而不是您正在使用的技巧是一种更好的方法。这不会在整个历史记录中替换子模块的URL!相反,这会使所有原始提交保持不变。这仅仅意味着,对于您的帐户,因为您使用了
git config--global
:当您的git将要访问原始URL时,其他用户都不会受到此影响,而是会切换到替换URL

为了让它对任何其他用户起作用,这些其他用户必须采取相同的
git config
步骤。如果这是一个问题,您需要“用新存储库(表示备用历史的全新提交)替换存储库(所有提交,这是历史记录)”方法


1如果重写的“备用历史记录”从未重写的提交开始,则备用历史记录几乎是全新的,而不是全新的。从某种意义上说,这是更糟糕的,因为它更容易意外地重新介绍原始历史。然后你有两个历史,很难分辨哪一个是“真实的”


2它似乎没有一个有针对性的“修复子模块URL”选项,但这是一个合理的要求。在内部,这相当于过滤名为
.gitmodules
的文件,因此应该很容易实现。

感谢torek,这是一个有用的答案。很高兴知道
git config
是一条死胡同,这将节省我很多浪费的时间。我现在已经安装了
git filter repo
,并在我的Windows PC上运行,这是向前迈出的一步。不确定它如何或是否能够更新子模块URL,但一旦找到方法(或失败!),我将坚持并发回。我认为(实际上还没有尝试过),您应该在python代码中定义一个blob回调,并让它检查blob是否为
.gitmodules
文件。如果您没有为blob获取至少一个名称,这可能会有问题:您可能需要检查树并使用它来查找要重写的blob。无论哪种方式,一旦您有了
.gitmodules
blob文本,您只需使用简单的Python代码来搜索和替换URL。