diff --git a/Documentation/git-remote.adoc b/Documentation/git-remote.adoc
index 315100409d..1f490819ba 100644
--- a/Documentation/git-remote.adoc
+++ b/Documentation/git-remote.adoc
@@ -10,7 +10,7 @@ SYNOPSIS
--------
[synopsis]
git remote [-v | --verbose]
-git remote add [-t <branch>] [-m <master>] [-f] [--[no-]tags] [--mirror=(fetch|push)] <name> <URL>
+git remote add [-t <branch>] [-m <master>] [-f] [--[no-]tags] [--mirror=(fetch|push)] [--[no-]limited-fetch] <name> <URL>
git remote rename [--[no-]progress] <old> <new>
git remote remove <name>
git remote set-head <name> (-a | --auto | -d | --delete | <branch>)
@@ -75,6 +75,12 @@ the `refs/remotes/<name>/` namespace, a refspec to track only _<branch>_
is created. You can give more than one `-t <branch>` to track
multiple branches without grabbing all branches.
+
+With `--limited-fetch` option, instead of a `remote.<name>.fetch` refspec
+that tracks all branches, `remote.<name>.fetchRefmap` is set up so that a
+refspec-less `git fetch <name>` only fetches branches our local branches
+are built on. See the `--refmap` entry in linkgit:git-fetch[1] for
+details.
++
With `-m <master>` option, a symbolic-ref `refs/remotes/<name>/HEAD` is set
up to point at remote's _<master>_ branch. See also the set-head command.
+
diff --git a/builtin/remote.c b/builtin/remote.c
index fb7e5b114f..5f8a8a2f71 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -179,6 +179,7 @@ static int add(int argc, const char **argv, const char *prefix,
{
int fetch = 0, fetch_tags = TAGS_DEFAULT;
unsigned mirror = MIRROR_NONE;
+ int limited_fetch = -1; /* unspecified */
struct string_list track = STRING_LIST_INIT_NODUP;
const char *master = NULL;
struct remote *remote;@@ -198,6 +199,8 @@ static int add(int argc, const char **argv, const char *prefix,
OPT_CALLBACK_F(0, "mirror", &mirror, "(push|fetch)",
N_("set up remote as a mirror to push to or fetch from"),
PARSE_OPT_OPTARG | PARSE_OPT_COMP_ARG, parse_mirror_opt),
+ OPT_BOOL(0, "limited-fetch", &limited_fetch,
+ N_("fetch only the branches we build on, instead of every branch")),
OPT_END()
};
@@ -211,6 +214,10 @@ static int add(int argc, const char **argv, const char *prefix,
die(_("specifying a master branch makes no sense with --mirror"));
if (mirror && !(mirror & MIRROR_FETCH) && track.nr)
die(_("specifying branches to track makes sense only with fetch mirrors"));
+ if (limited_fetch == 1 && track.nr)
+ die(_("--limited-fetch does not make sense with -t/--track"));
+ if (limited_fetch == 1 && mirror)
+ die(_("--limited-fetch does not make sense with --mirror"));
name = argv[0];
url = argv[1];@@ -230,13 +237,22 @@ static int add(int argc, const char **argv, const char *prefix,
repo_config_set(the_repository, buf.buf, url);
if (!mirror || mirror & MIRROR_FETCH) {
+ bool use_limited_fetch = mirror == MIRROR_NONE && track.nr == 0 &&
+ limited_fetch == 1;
+
strbuf_reset(&buf);
- strbuf_addf(&buf, "remote.%s.fetch", name);
- if (track.nr == 0)
- string_list_append(&track, "*");
- for (size_t i = 0; i < track.nr; i++) {
- add_branch(buf.buf, track.items[i].string,
- name, mirror, &buf2);
+ if (use_limited_fetch) {
+ strbuf_addf(&buf, "remote.%s.fetchRefmap", name);
+ strbuf_reset(&buf2);
+ strbuf_addf(&buf2, "+refs/heads/*:refs/remotes/%s/*", name);
+ repo_config_set(the_repository, buf.buf, buf2.buf);
+ } else {
+ strbuf_addf(&buf, "remote.%s.fetch", name);
+ if (track.nr == 0)
+ string_list_append(&track, "*");
+ for (size_t i = 0; i < track.nr; i++)
+ add_branch(buf.buf, track.items[i].string,
+ name, mirror, &buf2);
}
}
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 5fbfcb0848..90cba75f93 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -137,6 +137,22 @@ test_expect_success 'filters are listed by git remote -v only' '
test_grep ! "\[blob:none\]" out
'
+test_expect_success '--limited-fetch works in a full repository too' '
+ test_when_finished "rm -rf full-add" &&
+ git clone --no-local one full-add &&
+ (
+ cd full-add &&
+ git remote add --limited-fetch upstream ../two &&
+ test_cmp_config "+refs/heads/*:refs/remotes/upstream/*" \
+ remote.upstream.fetchRefmap &&
+ test_must_fail git config get remote.upstream.fetch
+ )
+'
+
+test_expect_success '--limited-fetch conflicts with -t' '
+ test_must_fail git remote add --limited-fetch -t main upstream ../two
+'
+
test_expect_success 'check remote-tracking' '
(
cd test &&
--
gitgitgadget