Skip to content

Commit 0f5e885

Browse files
committed
Merge branch 'rc/fetch-refetch'
"git fetch --refetch" learned to fetch everything without telling the other side what we already have, which is useful when you cannot trust what you have in the local object store. * rc/fetch-refetch: docs: mention --refetch fetch option fetch: after refetch, encourage auto gc repacking t5615-partial-clone: add test for fetch --refetch fetch: add --refetch option builtin/fetch-pack: add --refetch option fetch-pack: add refetch fetch-negotiator: add specific noop initializer
2 parents 1b54f5b + 4963d3e commit 0f5e885

15 files changed

+197
-22
lines changed

Documentation/config/remote.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,7 @@ remote.<name>.promisor::
8282
objects.
8383

8484
remote.<name>.partialclonefilter::
85-
The filter that will be applied when fetching from this
86-
promisor remote.
85+
The filter that will be applied when fetching from this promisor remote.
86+
Changing or clearing this value will only affect fetches for new commits.
87+
To fetch associated objects for commits already present in the local object
88+
database, use the `--refetch` option of linkgit:git-fetch[1].

Documentation/fetch-options.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ endif::git-pull[]
163163
behavior for a remote may be specified with the remote.<name>.tagOpt
164164
setting. See linkgit:git-config[1].
165165

166+
ifndef::git-pull[]
167+
--refetch::
168+
Instead of negotiating with the server to avoid transferring commits and
169+
associated objects that are already present locally, this option fetches
170+
all objects as a fresh clone would. Use this to reapply a partial clone
171+
filter from configuration or using `--filter=` when the filter
172+
definition has changed. Automatic post-fetch maintenance will perform
173+
object database pack consolidation to remove any duplicate objects.
174+
endif::git-pull[]
175+
166176
--refmap=<refspec>::
167177
When fetching refs listed on the command line, use the
168178
specified refspec (can be given more than once) to map the

Documentation/git-fetch-pack.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ be in a separate packet, and the list must end with a flush packet.
101101
current shallow boundary instead of from the tip of each
102102
remote branch history.
103103

104+
--refetch::
105+
Skips negotiating commits with the server in order to fetch all matching
106+
objects. Use to reapply a new partial clone blob/tree filter.
107+
104108
--no-progress::
105109
Do not show the progress.
106110

Documentation/technical/partial-clone.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,9 @@ Fetching Missing Objects
181181
currently fetches all objects referred to by the requested objects, even
182182
though they are not necessary.
183183

184+
- Fetching with `--refetch` will request a complete new filtered packfile from
185+
the remote, which can be used to change a filter without needing to
186+
dynamically fetch missing objects.
184187

185188
Using many promisor remotes
186189
---------------------------

builtin/fetch-pack.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,10 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
153153
args.from_promisor = 1;
154154
continue;
155155
}
156+
if (!strcmp("--refetch", arg)) {
157+
args.refetch = 1;
158+
continue;
159+
}
156160
if (skip_prefix(arg, ("--filter="), &arg)) {
157161
parse_list_objects_filter(&args.filter_options, arg);
158162
continue;

builtin/fetch.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ static int prune_tags = -1; /* unspecified */
5959

6060
static int all, append, dry_run, force, keep, multiple, update_head_ok;
6161
static int write_fetch_head = 1;
62-
static int verbosity, deepen_relative, set_upstream;
62+
static int verbosity, deepen_relative, set_upstream, refetch;
6363
static int progress = -1;
6464
static int enable_auto_gc = 1;
6565
static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
@@ -190,6 +190,9 @@ static struct option builtin_fetch_options[] = {
190190
OPT_SET_INT_F(0, "unshallow", &unshallow,
191191
N_("convert to a complete repository"),
192192
1, PARSE_OPT_NONEG),
193+
OPT_SET_INT_F(0, "refetch", &refetch,
194+
N_("re-fetch without negotiating common commits"),
195+
1, PARSE_OPT_NONEG),
193196
{ OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
194197
N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
195198
OPT_CALLBACK_F(0, "recurse-submodules-default",
@@ -1304,6 +1307,14 @@ static int check_exist_and_connected(struct ref *ref_map)
13041307
if (deepen)
13051308
return -1;
13061309

1310+
/*
1311+
* Similarly, if we need to refetch, we always want to perform a full
1312+
* fetch ignoring existing objects.
1313+
*/
1314+
if (refetch)
1315+
return -1;
1316+
1317+
13071318
/*
13081319
* check_connected() allows objects to merely be promised, but
13091320
* we need all direct targets to exist.
@@ -1517,6 +1528,8 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
15171528
set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes");
15181529
if (update_shallow)
15191530
set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
1531+
if (refetch)
1532+
set_option(transport, TRANS_OPT_REFETCH, "yes");
15201533
if (filter_options.choice) {
15211534
const char *spec =
15221535
expand_list_objects_filter_spec(&filter_options);
@@ -2293,8 +2306,25 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
22932306
NULL);
22942307
}
22952308

2296-
if (enable_auto_gc)
2309+
if (enable_auto_gc) {
2310+
if (refetch) {
2311+
/*
2312+
* Hint auto-maintenance strongly to encourage repacking,
2313+
* but respect config settings disabling it.
2314+
*/
2315+
int opt_val;
2316+
if (git_config_get_int("gc.autopacklimit", &opt_val))
2317+
opt_val = -1;
2318+
if (opt_val != 0)
2319+
git_config_push_parameter("gc.autoPackLimit=1");
2320+
2321+
if (git_config_get_int("maintenance.incremental-repack.auto", &opt_val))
2322+
opt_val = -1;
2323+
if (opt_val != 0)
2324+
git_config_push_parameter("maintenance.incremental-repack.auto=-1");
2325+
}
22972326
run_auto_maintenance(verbosity < 0);
2327+
}
22982328

22992329
cleanup:
23002330
string_list_clear(&list, 0);

fetch-negotiator.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,8 @@ void fetch_negotiator_init(struct repository *r,
2323
return;
2424
}
2525
}
26+
27+
void fetch_negotiator_init_noop(struct fetch_negotiator *negotiator)
28+
{
29+
noop_negotiator_init(negotiator);
30+
}

fetch-negotiator.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,15 @@ struct fetch_negotiator {
5353
void *data;
5454
};
5555

56+
/*
57+
* Initialize a negotiator based on the repository settings.
58+
*/
5659
void fetch_negotiator_init(struct repository *r,
5760
struct fetch_negotiator *negotiator);
5861

62+
/*
63+
* Initialize a noop negotiator.
64+
*/
65+
void fetch_negotiator_init_noop(struct fetch_negotiator *negotiator);
66+
5967
#endif

fetch-pack.c

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -312,19 +312,21 @@ static int find_common(struct fetch_negotiator *negotiator,
312312
const char *remote_hex;
313313
struct object *o;
314314

315-
/*
316-
* If that object is complete (i.e. it is an ancestor of a
317-
* local ref), we tell them we have it but do not have to
318-
* tell them about its ancestors, which they already know
319-
* about.
320-
*
321-
* We use lookup_object here because we are only
322-
* interested in the case we *know* the object is
323-
* reachable and we have already scanned it.
324-
*/
325-
if (((o = lookup_object(the_repository, remote)) != NULL) &&
326-
(o->flags & COMPLETE)) {
327-
continue;
315+
if (!args->refetch) {
316+
/*
317+
* If that object is complete (i.e. it is an ancestor of a
318+
* local ref), we tell them we have it but do not have to
319+
* tell them about its ancestors, which they already know
320+
* about.
321+
*
322+
* We use lookup_object here because we are only
323+
* interested in the case we *know* the object is
324+
* reachable and we have already scanned it.
325+
*/
326+
if (((o = lookup_object(the_repository, remote)) != NULL) &&
327+
(o->flags & COMPLETE)) {
328+
continue;
329+
}
328330
}
329331

330332
remote_hex = oid_to_hex(remote);
@@ -692,6 +694,9 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator,
692694
int old_save_commit_buffer = save_commit_buffer;
693695
timestamp_t cutoff = 0;
694696

697+
if (args->refetch)
698+
return;
699+
695700
save_commit_buffer = 0;
696701

697702
trace2_region_enter("fetch-pack", "parse_remote_refs_and_find_cutoff", NULL);
@@ -1028,7 +1033,11 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
10281033
struct fetch_negotiator *negotiator;
10291034

10301035
negotiator = &negotiator_alloc;
1031-
fetch_negotiator_init(r, negotiator);
1036+
if (args->refetch) {
1037+
fetch_negotiator_init_noop(negotiator);
1038+
} else {
1039+
fetch_negotiator_init(r, negotiator);
1040+
}
10321041

10331042
sort_ref_list(&ref, ref_compare_name);
10341043
QSORT(sought, nr_sought, cmp_ref_by_name);
@@ -1121,7 +1130,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
11211130

11221131
mark_complete_and_common_ref(negotiator, args, &ref);
11231132
filter_refs(args, &ref, sought, nr_sought);
1124-
if (everything_local(args, &ref)) {
1133+
if (!args->refetch && everything_local(args, &ref)) {
11251134
packet_flush(fd[1]);
11261135
goto all_done;
11271136
}
@@ -1587,7 +1596,10 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
15871596
struct strvec index_pack_args = STRVEC_INIT;
15881597

15891598
negotiator = &negotiator_alloc;
1590-
fetch_negotiator_init(r, negotiator);
1599+
if (args->refetch)
1600+
fetch_negotiator_init_noop(negotiator);
1601+
else
1602+
fetch_negotiator_init(r, negotiator);
15911603

15921604
packet_reader_init(&reader, fd[0], NULL, 0,
15931605
PACKET_READ_CHOMP_NEWLINE |
@@ -1613,7 +1625,7 @@ static struct ref *do_fetch_pack_v2(struct fetch_pack_args *args,
16131625
/* Filter 'ref' by 'sought' and those that aren't local */
16141626
mark_complete_and_common_ref(negotiator, args, &ref);
16151627
filter_refs(args, &ref, sought, nr_sought);
1616-
if (everything_local(args, &ref))
1628+
if (!args->refetch && everything_local(args, &ref))
16171629
state = FETCH_DONE;
16181630
else
16191631
state = FETCH_SEND_REQUEST;

fetch-pack.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct fetch_pack_args {
4242
unsigned update_shallow:1;
4343
unsigned reject_shallow_remote:1;
4444
unsigned deepen:1;
45+
unsigned refetch:1;
4546

4647
/*
4748
* Indicate that the remote of this request is a promisor remote. The

0 commit comments

Comments
 (0)