[PATCH v3 1/4] fetch: add remote.<name>.refmap
- From
Harald Nordgren via GitGitGadget <gitgitgadget@gmail.com>
- Date
- Sep 25, 2026, 10:49 UTC
- Message-ID
- <b04c00b974ce488ea1eb82556040fb54c05dad5a.1790333402.git.gitgitgadget@gmail.com>
- In-Reply-To
- <pull.2412.v3.git.git.1790333402.gitgitgadget@gmail.com>
From: Harald Nordgren <haraldnordgren@gmail.com>
Add a per-remote config variable, remote.<name>.refmap, that provides the default value for --refmap the same way remote.<name>.fetch already provides the default refspecs to fetch. It only takes effect when there is something explicit to fetch, on the command line or via remote.<name>.fetch, matching how --refmap itself already behaves.
Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com> --- Documentation/config/remote.adoc | 6 ++++++ Documentation/fetch-options.adoc | 3 +++ builtin/fetch.c | 8 +++++--- remote.c | 12 +++++++++++- remote.h | 6 ++++++ t/t5510-fetch.sh | 17 +++++++++++++++++ 6 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/Documentation/config/remote.adoc b/Documentation/config/remote.adoc index 3a20d0f752..00f9ed8d3d 100644 --- a/Documentation/config/remote.adoc +++ b/Documentation/config/remote.adoc @@ -33,6 +33,12 @@ remote.<name>.fetch:: The default set of "refspec" for linkgit:git-fetch[1]. See linkgit:git-fetch[1]. +remote.<name>.refmap:: + The default value of the `--refmap` option for linkgit:git-fetch[1]. + Only takes effect when the fetch names what to fetch explicitly, + either on the command line or via `remote.<name>.fetch`. See the + `--refmap` entry in linkgit:git-fetch[1]. + remote.<name>.push:: The default set of "refspec" for linkgit:git-push[1]. See linkgit:git-push[1]. diff --git a/Documentation/fetch-options.adoc b/Documentation/fetch-options.adoc index 035f780e58..538914bc6e 100644 --- a/Documentation/fetch-options.adoc +++ b/Documentation/fetch-options.adoc @@ -244,6 +244,9 @@ endif::git-pull[] refspecs and rely entirely on the refspecs supplied as command-line arguments. See section on "Configured Remote-tracking Branches" for details. ++ +`remote.<name>.refmap` provides the default value for this option, the +same way `remote.<name>.fetch` provides the default refspecs to fetch. `-t`:: `--tags`:: diff --git a/builtin/fetch.c b/builtin/fetch.c index 533fdfe7d8..7651b41139 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -509,6 +509,8 @@ static struct ref *get_ref_map(struct remote *remote, struct ref *rm; struct ref *ref_map = NULL; struct ref **tail = &ref_map; + struct refspec *effective_refmap = + refmap.nr ? &refmap : remote ? &remote->refmap : NULL; /* opportunistically-updated references: */ struct ref *orefs = NULL, **oref_tail = &orefs; @@ -552,14 +554,14 @@ static struct ref *get_ref_map(struct remote *remote, * by ref_remove_duplicates() in favor of one of these * opportunistic entries with FETCH_HEAD_IGNORE. */ - if (refmap.nr) - fetch_refspec = &refmap; + if (effective_refmap && effective_refmap->nr) + fetch_refspec = effective_refmap; else fetch_refspec = &remote->fetch; for (i = 0; i < fetch_refspec->nr; i++) get_fetch_map(ref_map, &fetch_refspec->items[i], &oref_tail, 1); - } else if (refmap.nr) { + } else if (effective_refmap && effective_refmap->nr) { die("--refmap option is only meaningful with command-line refspec(s)"); } else { /* Use the defaults */ diff --git a/remote.c b/remote.c index fe62068463..017cd9d13e 100644 --- a/remote.c +++ b/remote.c @@ -152,6 +152,7 @@ static struct remote *make_remote(struct remote_state *remote_state, ret->name = xstrndup(name, len); refspec_init_push(&ret->push, the_hash_algo); refspec_init_fetch(&ret->fetch, the_hash_algo); + refspec_init_fetch(&ret->refmap, the_hash_algo); string_list_init_dup(&ret->server_options); string_list_init_dup(&ret->negotiation_restrict); string_list_init_dup(&ret->negotiation_include); @@ -176,6 +177,7 @@ static void remote_clear(struct remote *remote) refspec_clear(&remote->push); refspec_clear(&remote->fetch); + refspec_clear(&remote->refmap); free((char *)remote->receivepack); free((char *)remote->uploadpack); @@ -539,6 +541,12 @@ static int handle_config(const char *key, const char *value, return -1; refspec_append(&remote->fetch, v); free(v); + } else if (!strcmp(subkey, "refmap")) { + char *v; + if (git_config_string(&v, key, value)) + return -1; + refspec_append(&remote->refmap, v); + free(v); } else if (!strcmp(subkey, "receivepack")) { char *v; if (git_config_string(&v, key, value)) @@ -988,7 +996,9 @@ void ref_push_report_free(struct ref_push_report *report) int remote_find_tracking(struct remote *remote, struct refspec_item *refspec) { - return refspec_find_match(&remote->fetch, refspec); + if (remote->fetch.nr) + return refspec_find_match(&remote->fetch, refspec); + return refspec_find_match(&remote->refmap, refspec); } static struct ref *alloc_ref_with_prefix(const char *prefix, size_t prefixlen, diff --git a/remote.h b/remote.h index cca02033b9..ac485a584d 100644 --- a/remote.h +++ b/remote.h @@ -90,6 +90,12 @@ struct remote { struct refspec fetch; + /* + * How to map refs fetched without an explicit destination into our + * own namespace, the same as the --refmap command line option. + */ + struct refspec refmap; + /* * The setting for whether to fetch tags (as a separate rule from the * configured refspecs); diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh index a8d38d9176..bd853d0a84 100755 --- a/t/t5510-fetch.sh +++ b/t/t5510-fetch.sh @@ -927,6 +927,23 @@ test_expect_success 'explicit --refmap option overrides remote.*.fetch' ' ) ' +test_expect_success 'remote.*.refmap acts like --refmap on the command line' ' + test_when_finished "git -C three config --unset remote.origin.refmap" && + git branch -f side && + git -C three config remote.origin.refmap \ + "refs/heads/*:refs/remotes/other/*" && + ( + cd three && + git update-ref refs/remotes/origin/main base-origin-main && + o=$(git rev-parse --verify refs/remotes/origin/main) && + git fetch origin main && + n=$(git rev-parse --verify refs/remotes/origin/main) && + test "$o" = "$n" && + test_must_fail git rev-parse --verify refs/remotes/origin/side && + git rev-parse --verify refs/remotes/other/main + ) +' + test_expect_success 'explicitly empty --refmap option disables remote.*.fetch' ' git branch -f side && (
-- gitgitgadget