From ca62f524c1eaef606b5c312de53ef7c4d9eefa4f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Mon, 23 Jun 2025 16:11:35 -0700 Subject: submodule: look up remotes by URL first The get_default_remote_submodule() function performs a lookup to find the appropriate remote to use within a submodule. The function first checks to see if it can find the remote for the current branch. If this fails, it then checks to see if there is exactly one remote. It will use this, before finally falling back to "origin" as the default. If a user happens to rename their default remote from origin, either manually or by setting something like clone.defaultRemoteName, this fallback will not work. In such cases, the submodule logic will try to use a non-existent remote. This usually manifests as a failure to trigger the submodule update. The parent project already knows and stores the submodule URL in either .gitmodules or its .git/config. Add a new repo_remote_from_url() helper which will iterate over all the remotes in a repository and return the first remote which has a matching URL. Refactor get_default_remote_submodule to find the submodule and get its URL. If a valid URL exists, first try to obtain a remote using the new repo_remote_from_url(). Fall back to the repo_default_remote() otherwise. The fallback logic is kept in case for some reason the user has manually changed the URL within the submodule. Additionally, we still try to use a remote rather than directly passing the URL in the fetch_in_submodule() logic. This ensures that an update will properly update the remote refs within the submodule as expected, rather than just fetching into FETCH_HEAD. Signed-off-by: Jacob Keller Signed-off-by: Junio C Hamano --- remote.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'remote.c') diff --git a/remote.c b/remote.c index e35cf7ec61..60b4aec3de 100644 --- a/remote.c +++ b/remote.c @@ -1801,6 +1801,21 @@ const char *repo_default_remote(struct repository *repo) return remotes_remote_for_branch(repo->remote_state, branch, NULL); } +const char *repo_remote_from_url(struct repository *repo, const char *url) +{ + read_config(repo, 0); + + 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; + } + return NULL; +} + int branch_has_merge_config(struct branch *branch) { return branch && branch->set_merge; -- cgit v1.3