]> git.ipfire.org Git - thirdparty/git.git/commitdiff
submodule: resolve insteadOf aliases when matching remote
authorÉric NICOLAS <ccjmne@gmail.com>
Thu, 23 Jul 2026 00:21:32 +0000 (02:21 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 23 Jul 2026 03:24:21 +0000 (20:24 -0700)
When ca62f524c1 (submodule: look up remotes by URL first, 2025-06-23)
introduced a mechanism to identify which remote is to be used by a
submodule, it compared the URL stored in the .gitmodules inventory to
that of each available remote.

The URLs of remotes are rewritten according to url.<base>.insteadOf,
whereas those stored in the .gitmodules aren't.  When such aliasing
applies, no match can be made between the two corresponding sides, and
the procedure degrades to its fallback logic electing either the only
configured remote if there is only one, or "origin" otherwise.

That behaviour is unfortunate when no remote is called "origin",
because its last resort will have a submodule update command look for a
non-existent remote-tracking reference and fail to proceed, instead of
using the remote whose rewritten URL matches.

Resolve the alias in the URL inventoried in .gitmodules before comparing
it against those of the corresponding submodule's configured remotes.

Signed-off-by: Éric NICOLAS <ccjmne@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
remote.c
t/t7406-submodule-update.sh

index b17648d6ef32e4f438ff9426571d369421e84886..b1fed58e79e35eee1e145b736c7faf28cb3b6991 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1821,17 +1821,25 @@ const char *repo_default_remote(struct repository *repo)
 
 const char *repo_remote_from_url(struct repository *repo, const char *url)
 {
+       char *rewritten_url;
+       const char *remote_name = NULL;
+
        read_config(repo, 0);
+       if ((rewritten_url = alias_url(url, &repo->remote_state->rewrites)))
+               url = rewritten_url;
 
        for (int i = 0; i < repo->remote_state->remotes_nr; i++) {
                struct remote *remote = repo->remote_state->remotes[i];
                if (!remote)
                        continue;
 
-               if (remote_has_url(remote, url))
-                       return remote->name;
+               if (remote_has_url(remote, url)) {
+                       remote_name = remote->name;
+                       break;
+               }
        }
-       return NULL;
+       free(rewritten_url);
+       return remote_name;
 }
 
 int branch_has_merge_config(struct branch *branch)
index 9554720152f6f0078c9ccee06b8d8eb2110dfb7f..10adeabf0fcc8595fc05ffb22dfd03f1563c9b02 100755 (executable)
@@ -256,6 +256,25 @@ test_expect_success 'submodule update --remote should fetch upstream changes' '
        )
 '
 
+test_expect_success 'submodule update --remote resolves URL rewrites' '
+       test_config_global "url.$(pwd)/.insteadOf" local: &&
+       mkdir alias-super alias-submodule &&
+       (
+               cd alias-submodule &&
+               git init &&
+               git commit --allow-empty --message "Initial commit"
+       ) &&
+       (
+               cd alias-super &&
+               git init &&
+               git submodule add local:alias-submodule submodule &&
+               git submodule update --force &&
+               git -C submodule remote rename origin upstream &&
+               git -C submodule remote add fork user@host &&
+               git submodule update --remote
+       )
+'
+
 test_expect_success 'submodule update --remote should fetch upstream changes with .' '
        (
                cd super &&