summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Robert Coup <robert@coup.net.nz>2022-03-28 14:02:08 +0000
committerLibravatar Junio C Hamano <gitster@pobox.com>2022-03-28 10:25:52 -0700
commit3c7bab06e12922fbcb375187eb60ac426fc72a3a (patch)
treee1ebe117e15be200ddd71cafdb2bff01ad64a25a
parentbuiltin/fetch-pack: add --refetch option (diff)
downloadtgif-3c7bab06e12922fbcb375187eb60ac426fc72a3a.tar.xz
fetch: add --refetch option
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>
-rw-r--r--Documentation/fetch-options.txt9
-rw-r--r--builtin/fetch.c15
-rw-r--r--transport-helper.c3
-rw-r--r--transport.c4
-rw-r--r--transport.h4
5 files changed, 34 insertions, 1 deletions
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index f903683189..21a247abfa 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -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
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 79ee959185..aa53ada58a 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -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",
@@ -1297,6 +1300,14 @@ static int check_exist_and_connected(struct ref *ref_map)
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);
diff --git a/transport-helper.c b/transport-helper.c
index a0297b0986..b4dbbabb0c 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -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);
diff --git a/transport.c b/transport.c
index 253d6671b1..e2817b7a71 100644
--- a/transport.c
+++ b/transport.c
@@ -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;
diff --git a/transport.h b/transport.h
index a0bc6a1e9e..12bc08fc33 100644
--- a/transport.h
+++ b/transport.h
@@ -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"