简体   繁体   English

如何更改 git 子模块的远程存储库?

[英]How to change the remote repository for a git submodule?

I've created a git repository with a submodule in it.我创建了一个带有子模块的 git 存储库。 I'm able to tell the submodule itself to change its remote repository path, but I'm not sure how to tell the parent repository how to change the remote repository path for the submodule.我可以告诉子模块本身更改其远程存储库路径,但我不确定如何告诉父存储库如何更改子模块的远程存储库路径。

I wouldn't be surprised if I'm somewhat out of luck and have to do things manually, as even deleting submodules isn't easy.如果我有点不走运并且必须手动执行操作,我不会感到惊讶,因为即使删除子模块也不容易。

You should just be able to edit the .gitmodules file to update the URL and then run git submodule sync --recursive to reflect that change to the superproject and your working copy.您应该能够编辑.gitmodules文件以更新 URL,然后运行git submodule sync --recursive以将更改反映到超级项目和您的工作副本。

Then you need to go to the .git/modules/path_to_submodule dir and change its config file to update git path.然后您需要转到.git/modules/path_to_submodule目录并更改其配置文件以更新 git 路径。

If repo history is different then you need to checkout new branch manually:如果 repo 历史记录不同,那么您需要手动检出新分支:

git submodule sync --recursive
cd <submodule_dir> 

git fetch
git checkout origin/master
git branch master -f
git checkout master

These commands will do the work on command prompt without altering any files on local repository这些命令将在命令提示符下完成工作,而不会更改本地存储库中的任何文件

git config --file=.gitmodules submodule.Submod.url https://github.com/username/ABC.git
git config --file=.gitmodules submodule.Submod.branch Development
git submodule sync
git submodule update --init --recursive --remote

Please look at the blog for screenshots: Changing GIT submodules URL/Branch to other URL/branch of same repository请查看博客截图: 将 GIT 子模块 URL/Branch 更改为同一存储库的其他 URL/分支

With Git 2.25 (Q1 2020), you can modify it.使用 Git 2.25(2020 年第一季度),您可以对其进行修改
See " Git submodule url changed " and the new command参见“ Git submodule url changed ”和新命令

git submodule set-url [--] <path> <newurl>

Warning: Hi-Angel mentions in the comments (tested even with Git 2.31.1):警告: Hi-Angel 在评论中提到(即使使用 Git 2.31.1 测试):

One should be careful with git submodule set-url because it has a bug:应该小心使用git submodule set-url因为它有一个错误:

If, inside your .gitmodules file, the path looks like this some-path , and then you execute a git submodule set-url some-path/ new-url (note the trailing slash / ), then, instead of modifying existing submodule, the command will add another one.如果在你的.gitmodules文件中,路径看起来像这样some-path ,然后你执行一个git submodule set-url some-path/ new-url (注意尾部斜杠/ ),那么,而不是修改现有的子模块,该命令将添加另一个。


Original answer (May 2009, ten years ago)原始答案(2009 年 5 月,十年前)

Actually, a patch has been submitted in April 2009 to clarify gitmodule role.实际上, 2009 年 4 月已经提交了一个补丁来澄清gitmodule作用。

So now the gitmodule documentation does not yet include:所以现在gitmodule 文档还没有包括:

The .gitmodules file, located in the top-level directory of a git working tree, is a text file with a syntax matching the requirements -of linkgit:git-config 3 . .gitmodules文件位于 git 工作树的顶级目录中,是一个文本文件,其语法符合 -of linkgit:git-config 3 的要求
[NEW]: [新的]:
As this file is managed by Git, it tracks the +records of a project's submodules.由于此文件由 Git 管理,因此它会跟踪项目子模块的 + 记录。
Information stored in this file is used as a hint to prime the authoritative version of the record stored in the project configuration file.此文件中存储的信息用作提示,以准备存储在项目配置文件中的记录的权威版本。
User specific record changes (eg to account for differences in submodule URLs due to networking situations) should be made to the configuration file, while record changes to be propagated (eg +due to a relocation of the submodule source) should be made to this file.应该对配置文件进行用户特定的记录更改(例如,考虑到由于网络情况而导致子模块 URL 的差异),而要传播的记录更改(例如,由于子模块源的重新定位)应该对此文件进行.

That pretty much confirm Jim's answer .这几乎证实了吉姆的回答


If you follow this git submodule tutorial , you see you need a " git submodule init " to add the submodule repository URLs to .git/config.如果你遵循这个git submodule 教程,你会发现你需要一个“ git submodule init ”来将子模块存储库 URL 添加到 .git/config。

" git submodule sync " has been added in August 2008 precisely to make that task easier when URL changes (especially if the number of submodules is important). git submodule sync是在 2008 年 8 月添加的,目的是在 URL 更改时使该任务更容易(尤其是在子模块的数量很重要的情况下)。
The associate script with that command is straightforward enough:带有该命令的关联脚本非常简单:

module_list "$@" |
while read mode sha1 stage path
do
    name=$(module_name "$path")
    url=$(git config -f .gitmodules --get submodule."$name".url)
    if test -e "$path"/.git
    then
    (
        unset GIT_DIR
        cd "$path"
        remote=$(get_default_remote)
        say "Synchronizing submodule url for '$name'"
        git config remote."$remote".url "$url"
    )
    fi
done

The goal remains: git config remote."$remote".url "$url"目标仍然是: git config remote."$remote".url "$url"

In simple terms, you just need to edit the .gitmodules file, then resync and update:简单来说,你只需要编辑 .gitmodules 文件,然后重新同步和更新:

Edit the file, either via a git command or directly:通过 git 命令或直接编辑文件:

git config --file=.gitmodules -e

or just:要不就:

vim .gitmodules

then resync and update:然后重新同步并更新:

git submodule sync
git submodule update --init --recursive --remote

What worked for me (on Windows, using git version 1.8.3.msysgit.0):什么对我有用(在 Windows 上,使用 git 版本 1.8.3.msysgit.0):

  • Update .gitmodules with the URL to the new repository使用新存储库的 URL 更新 .gitmodules
  • Remove the corresponding line from the ".git/config" file从“.git/config”文件中删除相应的行
  • Delete the corresponding directory in the ".git/modules/external" directory (".git/modules" for recent git versions)删除“.git/modules/external”目录下的对应目录(“.git/modules”为最近的git版本)
  • Delete the checked out submodule directory itself (unsure if this is necessary)删除检出的子模块目录本身(不确定是否有必要)
  • Run git submodule init and git submodule update运行git submodule initgit submodule update
  • Make sure the checked out submodule is at the correct commit, and commit that, since it's likely that the hash will be different确保检出的子模块在正确的提交中,并提交,因为散列很可能会不同

After doing all that, everything is in the state I would expect.完成所有这些之后,一切都处于我期望的状态。 I imagine other users of the repository will have similar pain when they come to update though - it would be wise to explain these steps in your commit message!我想存储库的其他用户在更新时也会有类似的痛苦 - 在提交消息中解释这些步骤是明智的!

Just edit your .git/config file.只需编辑您的.git/config文件。 For example;例如; if you have a "common" submodule you can do this in the super-module:如果您有一个“通用”子模块,您可以在超级模块中执行此操作:

git config submodule.common.url /data/my_local_common

git config --file=.gitmodules -e打开默认编辑器,您可以在其中更新路径

A brute force approach:蛮力方法:

  • update the .gitmodules file in the supermodule to point to the new submodule url,更新超级模块中的.gitmodules文件以指向新的子模块 url,
  • add and commit the changes to supermodule/.gitmodules ,添加并提交更改到supermodule/.gitmodules
  • make a new clone of the supermodule somewhere else on your computer (making sure that the latest changes to the .gitmodules file are reflected in the clone),在您计算机上的其他位置制作超级模块的新克隆(确保对.gitmodules文件的最新更改反映在克隆中),
  • change your working directory to the new clone of the supermodule,将您的工作目录更改为超级模块的新克隆,
  • run git submodule update --init path-to-submodule on the submodule,git submodule update --init path-to-submodule上运行git submodule update --init path-to-submodule submodule ,

et voilà!等等! The submodule in the new clone of the supermodule is properly configured!超级模块的新克隆中的子模块配置正确!

A lot of people (both here and on the internet at large) suggest solutions that require manually editing or deleting multiple files.很多人(无论是在这里还是在互联网上)都提出了需要手动编辑或删除多个文件的解决方案。 But that really isn't needed!但这真的不需要!

Even in environments where Git 2.25 (and thus git submodule set-url <path> <newurl> ) are not available, the easiest solution is to simply "unregister" the submodule and add it again with the new URL.即使在 Git 2.25 (因此git submodule set-url <path> <newurl> )不可用的环境中,最简单的解决方案是简单地“取消注册”子模块并使用新 URL 再次添加它。

Depending on Git version and submodule setup, you might need to manually remove <path> before adding it again.根据 Git 版本和子模块设置,您可能需要在再次添加之前手动删除<path> No other manual actions needed!无需其他手动操作!

git submodule deinit <path>
rm -rf <path>
git submodule add <repository> [<path>]

After that the .gitmodules file will have a different URL and should be committed.之后.gitmodules文件将有一个不同的 URL 并且应该被提交。 All other places (config, working tree) have already been handled by git.所有其他地方(配置、工作树)已经由 git 处理。

To explain what deinit does, I'd like to quote from the Git manual:为了解释deinit作用,我想引用 Git 手册中的内容:

deinit [-f|--force] (--all|[--] <path>…​)

Unregister the given submodules, ie remove the whole submodule.$name section from .git/config together with their work tree.取消注册给定的子模块,即从 .git/config 中删除整个submodule.$name部分及其工作树。 Further calls [..] will skip any unregistered submodules until they are initialized again进一步调用 [..] 将跳过任何未注册的子模块,直到它们再次初始化

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM