How to change the remote repository for a git submodule?

GitGit Submodules

Git Problem Overview


I've created a git repository with a submodule in it. 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.

Git Solutions


Solution 1 - Git

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.

Then you need to go to the .git/modules/path_to_submodule dir and change its config file to update git path.

If repo history is different then you need to checkout new branch manually:

git submodule sync --recursive
cd <submodule_dir> 

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

Solution 2 - Git

With Git 2.25 (Q1 2020), you can modify it.
See "Git submodule url changed" and the new command

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

(On the -- separator, see "double hyphen as a signal to stop option interpretation and treat all following arguments literally")

Warning: Hi-Angel mentions in the comments (tested even with Git 2.31.1):

> One should be careful with git submodule set-url because it has a bug: > > 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.


Original answer (May 2009, ten years ago)

Actually, a patch has been submitted in April 2009 to clarify gitmodule role.

So now the gitmodule documentation does not yet include:

> 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-config4.
[NEW]:
> As this file is managed by Git, it tracks the +records of a project's submodules.
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 (e.g. to account for differences in submodule URLs due to networking situations) should be made to the configuration file, while record changes to be propagated (e.g. +due to a relocation of the submodule source) should be made to this file.

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 sync" has been added in August 2008 precisely to make that task easier when URL changes (especially if the number of submodules is important).
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"

Solution 3 - Git

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: http://pa1gitsolutions.blogspot.ca/2015/07/changing-git-submodules-urlbranch-to.html">Changing GIT submodules URL/Branch to other URL/branch of same repository

Solution 4 - Git

In simple terms, you just need to edit the .gitmodules file, then resync and update:

Edit the file, either via a git command or directly:

git config --file=.gitmodules -e

or just:

vim .gitmodules

then resync and update:

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

Solution 5 - Git

What worked for me (on Windows, using git version 1.8.3.msysgit.0):

  • Update .gitmodules with the URL to the new repository
  • Remove the corresponding line from the ".git/config" file
  • Delete the corresponding directory in the ".git/modules/external" directory (".git/modules" for recent git versions)
  • Delete the checked out submodule directory itself (unsure if this is necessary)
  • Run git submodule init and git 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!

Solution 6 - Git

Just edit your .git/config file. 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

Solution 7 - Git

git config --file=.gitmodules -e opens the default editor in which you can update the path

Solution 8 - Git

A brute force approach:

  • update the .gitmodules file in the supermodule to point to the new submodule url,
  • add and commit the changes to 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),
  • change your working directory to the new clone of the supermodule,
  • run git submodule update --init --remote path-to-submodule on the submodule,

et voilà! The submodule in the new clone of the supermodule is properly configured!

Solution 9 - Git

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.

Depending on Git version and submodule setup, you might need to manually remove <path> before adding it again. 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. All other places (config, working tree) have already been handled by git.

To explain what deinit does, I'd like to quote from the Git manual:

> deinit [-f|--force] (--all|[--] <path>…​) > > Unregister the given submodules, i.e. remove the whole submodule.$name section from .git/config together with their work tree. Further calls [..] will skip any unregistered submodules until they are initialized again

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrew GrimmView Question on Stackoverflow
Solution 1 - GitJim PulsView Answer on Stackoverflow
Solution 2 - GitVonCView Answer on Stackoverflow
Solution 3 - GitPavan Sokke NagarajView Answer on Stackoverflow
Solution 4 - GitMatthew WilcoxsonView Answer on Stackoverflow
Solution 5 - GitBen HymersView Answer on Stackoverflow
Solution 6 - GitFelipeCView Answer on Stackoverflow
Solution 7 - GitLuGoView Answer on Stackoverflow
Solution 8 - GitJashaView Answer on Stackoverflow
Solution 9 - GitPothercaView Answer on Stackoverflow