]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fetch: add --refetch option
authorRobert Coup <robert@coup.net.nz>
Mon, 28 Mar 2022 14:02:08 +0000 (14:02 +0000)
committerJunio C Hamano <gitster@pobox.com>
Mon, 28 Mar 2022 17:25:52 +0000 (10:25 -0700)
Teach fetch and transports the --refetch option to force a full fetch
without negotiating common commits with the remote. Use when applying a
new partial clone filter to refetch all matching objects.

Signed-off-by: Robert Coup <robert@coup.net.nz>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/fetch-options.txt
builtin/fetch.c
transport-helper.c
transport.c
transport.h

index f9036831898f4ea275d6682f17c17479d4fb0953..21a247abfa4f67699ce04face235856450e6a516 100644 (file)
@@ -163,6 +163,15 @@ endif::git-pull[]
        behavior for a remote may be specified with the remote.<name>.tagOpt
        setting. See linkgit:git-config[1].
 
+ifndef::git-pull[]
+--refetch::
+       Instead of negotiating with the server to avoid transferring commits and
+       associated objects that are already present locally, this option fetches
+       all objects as a fresh clone would. Use this to reapply a partial clone
+       filter from configuration or using `--filter=` when the filter
+       definition has changed.
+endif::git-pull[]
+
 --refmap=<refspec>::
        When fetching refs listed on the command line, use the
        specified refspec (can be given more than once) to map the
index 79ee9591859e790122809a7241e49e6b70b2edde..aa53ada58ac68e8b74ade93ccd427e5eb6ee119b 100644 (file)
@@ -59,7 +59,7 @@ static int prune_tags = -1; /* unspecified */
 
 static int all, append, dry_run, force, keep, multiple, update_head_ok;
 static int write_fetch_head = 1;
-static int verbosity, deepen_relative, set_upstream;
+static int verbosity, deepen_relative, set_upstream, refetch;
 static int progress = -1;
 static int enable_auto_gc = 1;
 static int tags = TAGS_DEFAULT, unshallow, update_shallow, deepen;
@@ -190,6 +190,9 @@ static struct option builtin_fetch_options[] = {
        OPT_SET_INT_F(0, "unshallow", &unshallow,
                      N_("convert to a complete repository"),
                      1, PARSE_OPT_NONEG),
+       OPT_SET_INT_F(0, "refetch", &refetch,
+                     N_("re-fetch without negotiating common commits"),
+                     1, PARSE_OPT_NONEG),
        { OPTION_STRING, 0, "submodule-prefix", &submodule_prefix, N_("dir"),
                   N_("prepend this to submodule path output"), PARSE_OPT_HIDDEN },
        OPT_CALLBACK_F(0, "recurse-submodules-default",
@@ -1296,6 +1299,14 @@ static int check_exist_and_connected(struct ref *ref_map)
        if (deepen)
                return -1;
 
+       /*
+        * Similarly, if we need to refetch, we always want to perform a full
+        * fetch ignoring existing objects.
+        */
+       if (refetch)
+               return -1;
+
+
        /*
         * check_connected() allows objects to merely be promised, but
         * we need all direct targets to exist.
@@ -1492,6 +1503,8 @@ static struct transport *prepare_transport(struct remote *remote, int deepen)
                set_option(transport, TRANS_OPT_DEEPEN_RELATIVE, "yes");
        if (update_shallow)
                set_option(transport, TRANS_OPT_UPDATE_SHALLOW, "yes");
+       if (refetch)
+               set_option(transport, TRANS_OPT_REFETCH, "yes");
        if (filter_options.choice) {
                const char *spec =
                        expand_list_objects_filter_spec(&filter_options);
index a0297b0986c62e7a6e8f8951071ed5ea9da2640b..b4dbbabb0c2ef6c95b9e08f5bc7abc67322e27d4 100644 (file)
@@ -715,6 +715,9 @@ static int fetch_refs(struct transport *transport,
        if (data->transport_options.update_shallow)
                set_helper_option(transport, "update-shallow", "true");
 
+       if (data->transport_options.refetch)
+               set_helper_option(transport, "refetch", "true");
+
        if (data->transport_options.filter_options.choice) {
                const char *spec = expand_list_objects_filter_spec(
                        &data->transport_options.filter_options);
index 253d6671b1f1edb889525b0ed8a2bb2769540b33..e2817b7a71549b2bbf920420d44a2e87dddebe9a 100644 (file)
@@ -243,6 +243,9 @@ static int set_git_option(struct git_transport_options *opts,
                list_objects_filter_die_if_populated(&opts->filter_options);
                parse_list_objects_filter(&opts->filter_options, value);
                return 0;
+       } else if (!strcmp(name, TRANS_OPT_REFETCH)) {
+               opts->refetch = !!value;
+               return 0;
        } else if (!strcmp(name, TRANS_OPT_REJECT_SHALLOW)) {
                opts->reject_shallow = !!value;
                return 0;
@@ -377,6 +380,7 @@ static int fetch_refs_via_pack(struct transport *transport,
        args.update_shallow = data->options.update_shallow;
        args.from_promisor = data->options.from_promisor;
        args.filter_options = data->options.filter_options;
+       args.refetch = data->options.refetch;
        args.stateless_rpc = transport->stateless_rpc;
        args.server_options = transport->server_options;
        args.negotiation_tips = data->options.negotiation_tips;
index a0bc6a1e9eba8f7e3c034abc6ba5e0d685782959..12bc08fc33949a2caa7d95b0143f58751b899b77 100644 (file)
@@ -16,6 +16,7 @@ struct git_transport_options {
        unsigned update_shallow : 1;
        unsigned reject_shallow : 1;
        unsigned deepen_relative : 1;
+       unsigned refetch : 1;
 
        /* see documentation of corresponding flag in fetch-pack.h */
        unsigned from_promisor : 1;
@@ -216,6 +217,9 @@ void transport_check_allowed(const char *type);
 /* Filter objects for partial clone and fetch */
 #define TRANS_OPT_LIST_OBJECTS_FILTER "filter"
 
+/* Refetch all objects without negotiating */
+#define TRANS_OPT_REFETCH "refetch"
+
 /* Request atomic (all-or-nothing) updates when pushing */
 #define TRANS_OPT_ATOMIC "atomic"