Skip to content

Commit 80af121

Browse files
committed
remote: prefetch config
Large repositories often contain numerous branches and refs, many of which individual users may not need. This commit introduces a new configuration option (`remote.<remote>.prefetch`) to allow users to specify which remotes to prefetch during the maintenance task. Key behaviors: 1. If `remote.<remote>.prefetch` is unset or true, running `git-maintenance` will prefetch all refs for the remote. 2. If `remote.<remote>.prefetch` is set to false, the remote will be ignored for prefetching. In a future change, we could also allow restricting the refs that are prefetched per remote using the `prefetchref` config option per remote. Both of these options in unison would allow users to optimize their prefetch operations, reducing network traffic and disk usage. Signed-off-by: Shubham Kanodia <shubham.kanodia10@gmail.com>
1 parent 2e7b89e commit 80af121

File tree

6 files changed

+59
-3
lines changed

6 files changed

+59
-3
lines changed

Documentation/config/remote.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ remote.<name>.fetch::
3333
The default set of "refspec" for linkgit:git-fetch[1]. See
3434
linkgit:git-fetch[1].
3535

36+
remote.<name>.prefetch::
37+
If false, refs from the remote would not be prefetched for
38+
the prefetch task in linkgit:git-maintenance[1]. If not set,
39+
the value is assumed to be true.
40+
3641
remote.<name>.push::
3742
The default set of "refspec" for linkgit:git-push[1]. See
3843
linkgit:git-push[1].

Documentation/git-maintenance.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ commit-graph::
9797

9898
prefetch::
9999
The `prefetch` task updates the object directory with the latest
100-
objects from all registered remotes. For each remote, a `git fetch`
101-
command is run. The configured refspec is modified to place all
102-
requested refs within `refs/prefetch/`. Also, tags are not updated.
100+
objects from all registered remotes unless they've disabled prefetch
101+
using `remote.<remote>.prefetch` set to `false`. For each such remote,
102+
a `git fetch` command is run. The configured refspec is modified to place
103+
all requested refs within `refs/prefetch/`. Also, tags are not updated.
103104
+
104105
This is done to avoid disrupting the remote-tracking branches. The end users
105106
expect these refs to stay unmoved unless they initiate a fetch. However,

builtin/gc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,9 @@ static int fetch_remote(struct remote *remote, void *cbdata)
10271027
if (remote->skip_default_update)
10281028
return 0;
10291029

1030+
if (!remote->prefetch_enabled)
1031+
return 0;
1032+
10301033
child.git_cmd = 1;
10311034
strvec_pushl(&child.args, "fetch", remote->name,
10321035
"--prefetch", "--prune", "--no-tags",

remote.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ static struct remote *make_remote(struct remote_state *remote_state,
140140
CALLOC_ARRAY(ret, 1);
141141
ret->prune = -1; /* unspecified */
142142
ret->prune_tags = -1; /* unspecified */
143+
ret->prefetch_enabled = 1;
143144
ret->name = xstrndup(name, len);
144145
refspec_init(&ret->push, REFSPEC_PUSH);
145146
refspec_init(&ret->fetch, REFSPEC_FETCH);
@@ -456,6 +457,8 @@ static int handle_config(const char *key, const char *value,
456457
remote->prune = git_config_bool(key, value);
457458
else if (!strcmp(subkey, "prunetags"))
458459
remote->prune_tags = git_config_bool(key, value);
460+
else if (!strcmp(subkey, "prefetch"))
461+
remote->prefetch_enabled = git_config_bool(key, value);
459462
else if (!strcmp(subkey, "url")) {
460463
if (!value)
461464
return config_error_nonbool(key);

remote.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ struct remote {
7777

7878
struct refspec fetch;
7979

80+
int prefetch_enabled;
81+
8082
/*
8183
* The setting for whether to fetch tags (as a separate rule from the
8284
* configured refspecs);

t/t7900-maintenance.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,48 @@ test_expect_success 'prefetch multiple remotes' '
245245
test_subcommand git fetch remote2 $fetchargs <skip-remote1.txt
246246
'
247247

248+
test_expect_success 'prefetch respects remote.*.prefetch config' '
249+
test_create_repo prefetch-test-config &&
250+
(
251+
cd prefetch-test-config &&
252+
test_commit initial &&
253+
test_create_repo clone1 &&
254+
test_create_repo clone2 &&
255+
test_create_repo clone3 &&
256+
257+
git remote add remote1 "file://$(pwd)/clone1" &&
258+
git remote add remote2 "file://$(pwd)/clone2" &&
259+
git remote add remote3 "file://$(pwd)/clone3" &&
260+
261+
git config remote.remote1.prefetch false &&
262+
git config remote.remote2.prefetch true &&
263+
# remote3 is left unset
264+
265+
# Make changes in all clones
266+
git -C clone1 switch -c one &&
267+
git -C clone2 switch -c two &&
268+
git -C clone3 switch -c three &&
269+
test_commit -C clone1 one &&
270+
test_commit -C clone2 two &&
271+
test_commit -C clone3 three &&
272+
273+
# Run maintenance prefetch task
274+
GIT_TRACE2_EVENT="$(pwd)/prefetch.txt" git maintenance run --task=prefetch 2>/dev/null &&
275+
276+
# Check that if remotes were prefetched properly
277+
fetchargs="--prefetch --prune --no-tags --no-write-fetch-head --recurse-submodules=no --quiet" &&
278+
test_subcommand ! git fetch remote1 $fetchargs <prefetch.txt &&
279+
test_subcommand git fetch remote2 $fetchargs <prefetch.txt &&
280+
test_subcommand git fetch remote3 $fetchargs <prefetch.txt &&
281+
282+
# Verify that changes are in the prefetch refs for remote2 and remote3, but not remote1
283+
test_must_fail git rev-parse refs/prefetch/remotes/remote1/one &&
284+
git fetch --all &&
285+
test_cmp_rev refs/remotes/remote2/two refs/prefetch/remotes/remote2/two &&
286+
test_cmp_rev refs/remotes/remote3/three refs/prefetch/remotes/remote3/three
287+
)
288+
'
289+
248290
test_expect_success 'loose-objects task' '
249291
# Repack everything so we know the state of the object dir
250292
git repack -adk &&

0 commit comments

Comments
 (0)