From cdbd70c43773d534aa81ea2c83905a45ff0e74e4 Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Tue, 18 Jun 2019 13:25:26 -0700 Subject: fetch: add --[no-]show-forced-updates argument After updating a set of remove refs during a 'git fetch', we walk the commits in the new ref value and not in the old ref value to discover if the update was a forced update. This results in two things happening during the command: 1. The line including the ref update has an additional "(forced-update)" marker at the end. 2. The ref log for that remote branch includes a bit saying that update is a forced update. For many situations, this forced-update message happens infrequently, or is a small bit of information among many ref updates. Many users ignore these messages, but the calculation required here slows down their fetches significantly. Keep in mind that they do not have the opportunity to calculate a commit-graph file containing the newly-fetched commits, so these comparisons can be very slow. Add a '--[no-]show-forced-updates' option that allows a user to skip this calculation. The only permanent result is dropping the forced-update bit in the reflog. Include a new fetch.showForcedUpdates config setting that allows this behavior without including the argument in every command. The config setting is overridden by the command-line arguments. Signed-off-by: Derrick Stolee Signed-off-by: Junio C Hamano --- builtin/fetch.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'builtin/fetch.c') diff --git a/builtin/fetch.c b/builtin/fetch.c index 4ba63d5ac6..571c255218 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -39,6 +39,7 @@ enum { }; static int fetch_prune_config = -1; /* unspecified */ +static int fetch_show_forced_updates = 1; static int prune = -1; /* unspecified */ #define PRUNE_BY_DEFAULT 0 /* do we prune by default? */ @@ -79,6 +80,11 @@ static int git_fetch_config(const char *k, const char *v, void *cb) return 0; } + if (!strcmp(k, "fetch.showforcedupdates")) { + fetch_show_forced_updates = git_config_bool(k, v); + return 0; + } + if (!strcmp(k, "submodule.recurse")) { int r = git_config_bool(k, v) ? RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF; @@ -169,6 +175,8 @@ static struct option builtin_fetch_options[] = { OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"), N_("report that we have only objects reachable from this object")), OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), + OPT_BOOL(0, "show-forced-updates", &fetch_show_forced_updates, + N_("check for forced-updates on all updated branches")), OPT_END() }; @@ -773,9 +781,10 @@ static int update_local_ref(struct ref *ref, return r; } - if (in_merge_bases(current, updated)) { + if (!fetch_show_forced_updates || in_merge_bases(current, updated)) { struct strbuf quickref = STRBUF_INIT; int r; + strbuf_add_unique_abbrev(&quickref, ¤t->object.oid, DEFAULT_ABBREV); strbuf_addstr(&quickref, ".."); strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV); -- cgit v1.3 From 377444b440eab3b6ef636df092f7f8299acf75bb Mon Sep 17 00:00:00 2001 From: Derrick Stolee Date: Tue, 18 Jun 2019 13:25:27 -0700 Subject: fetch: warn about forced updates in branch listing The --[no-]show-forced-updates option in 'git fetch' can be confusing for some users, especially if it is enabled via config setting and not by argument. Add advice to warn the user that the (forced update) messages were not listed. Additionally, warn users when the forced update check takes longer than ten seconds, and recommend that they disable the check. These messages can be disabled by the advice.fetchShowForcedUpdates config setting. Signed-off-by: Derrick Stolee Signed-off-by: Junio C Hamano --- Documentation/config/advice.txt | 4 ++++ advice.c | 2 ++ advice.h | 1 + builtin/fetch.c | 25 ++++++++++++++++++++++++- 4 files changed, 31 insertions(+), 1 deletion(-) (limited to 'builtin/fetch.c') diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt index ec4f6ae658..1f1e847fb4 100644 --- a/Documentation/config/advice.txt +++ b/Documentation/config/advice.txt @@ -4,6 +4,10 @@ advice.*:: can tell Git that you do not need help by setting these to 'false': + -- + fetchShowForcedUpdates:: + Advice shown when linkgit:git-fetch[1] takes a long time + to calculate forced updates after ref updates, or to warn + that the check is disabled. pushUpdateRejected:: Set this variable to 'false' if you want to disable 'pushNonFFCurrent', diff --git a/advice.c b/advice.c index ce5f374ecd..4b283be51a 100644 --- a/advice.c +++ b/advice.c @@ -3,6 +3,7 @@ #include "color.h" #include "help.h" +int advice_fetch_show_forced_updates = 1; int advice_push_update_rejected = 1; int advice_push_non_ff_current = 1; int advice_push_non_ff_matching = 1; @@ -59,6 +60,7 @@ static struct { const char *name; int *preference; } advice_config[] = { + { "fetchShowForcedUpdates", &advice_fetch_show_forced_updates }, { "pushUpdateRejected", &advice_push_update_rejected }, { "pushNonFFCurrent", &advice_push_non_ff_current }, { "pushNonFFMatching", &advice_push_non_ff_matching }, diff --git a/advice.h b/advice.h index e50f02cdfe..495e53255c 100644 --- a/advice.h +++ b/advice.h @@ -3,6 +3,7 @@ #include "git-compat-util.h" +extern int advice_fetch_show_forced_updates; extern int advice_push_update_rejected; extern int advice_push_non_ff_current; extern int advice_push_non_ff_matching; diff --git a/builtin/fetch.c b/builtin/fetch.c index 571c255218..cf7eb0dd8d 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -24,6 +24,8 @@ #include "list-objects-filter-options.h" #include "commit-reach.h" +#define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000) + static const char * const builtin_fetch_usage[] = { N_("git fetch [] [ [...]]"), N_("git fetch [] "), @@ -40,6 +42,7 @@ enum { static int fetch_prune_config = -1; /* unspecified */ static int fetch_show_forced_updates = 1; +static uint64_t forced_updates_ms = 0; static int prune = -1; /* unspecified */ #define PRUNE_BY_DEFAULT 0 /* do we prune by default? */ @@ -707,6 +710,7 @@ static int update_local_ref(struct ref *ref, enum object_type type; struct branch *current_branch = branch_get(NULL); const char *pretty_ref = prettify_refname(ref->name); + int fast_forward = 0; type = oid_object_info(the_repository, &ref->new_oid, NULL); if (type < 0) @@ -781,7 +785,15 @@ static int update_local_ref(struct ref *ref, return r; } - if (!fetch_show_forced_updates || in_merge_bases(current, updated)) { + if (fetch_show_forced_updates) { + uint64_t t_before = getnanotime(); + fast_forward = in_merge_bases(current, updated); + forced_updates_ms += (getnanotime() - t_before) / 1000000; + } else { + fast_forward = 1; + } + + if (fast_forward) { struct strbuf quickref = STRBUF_INIT; int r; @@ -980,6 +992,17 @@ static int store_updated_refs(const char *raw_url, const char *remote_name, " 'git remote prune %s' to remove any old, conflicting " "branches"), remote_name); + if (advice_fetch_show_forced_updates) { + if (!fetch_show_forced_updates) { + warning(_("Fetch normally indicates which branches had a forced update, but that check has been disabled.")); + warning(_("To re-enable, use '--show-forced-updates' flag or run 'git config fetch.showForcedUpdates true'.")); + } else if (forced_updates_ms > FORCED_UPDATES_DELAY_WARNING_IN_MS) { + warning(_("It took %.2f seconds to check forced updates. You can use '--no-show-forced-updates'\n"), + forced_updates_ms / 1000.0); + warning(_("or run 'git config fetch.showForcedUpdates false' to avoid this check.\n")); + } + } + abort: strbuf_release(¬e); free(url); -- cgit v1.3