Merge branch 'ds/fetch-disable-force-notice'

"git fetch" and "git pull" reports when a fetch results in
non-fast-forward updates to let the user notice unusual situation.
The commands learned "--no-shown-forced-updates" option to disable
this safety feature.

* ds/fetch-disable-force-notice:
  pull: add --[no-]show-forced-updates passthrough
  fetch: warn about forced updates in branch listing
  fetch: add --[no-]show-forced-updates argument
This commit is contained in:
Junio C Hamano 2019-07-09 15:25:46 -07:00
commit cde9a64ea3
8 changed files with 88 additions and 1 deletions

View File

@ -4,6 +4,10 @@ advice.*::
can tell Git that you do not need help by setting these to 'false': 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:: pushUpdateRejected::
Set this variable to 'false' if you want to disable Set this variable to 'false' if you want to disable
'pushNonFFCurrent', 'pushNonFFCurrent',

View File

@ -63,3 +63,8 @@ fetch.negotiationAlgorithm::
Unknown values will cause 'git fetch' to error out. Unknown values will cause 'git fetch' to error out.
+ +
See also the `--negotiation-tip` option for linkgit:git-fetch[1]. See also the `--negotiation-tip` option for linkgit:git-fetch[1].
fetch.showForcedUpdates::
Set to false to enable `--no-show-forced-updates` in
linkgit:git-fetch[1] and linkgit:git-pull[1] commands.
Defaults to true.

View File

@ -225,6 +225,19 @@ endif::git-pull[]
When multiple `--server-option=<option>` are given, they are all When multiple `--server-option=<option>` are given, they are all
sent to the other side in the order listed on the command line. sent to the other side in the order listed on the command line.
--show-forced-updates::
By default, git checks if a branch is force-updated during
fetch. This can be disabled through fetch.showForcedUpdates, but
the --show-forced-updates option guarantees this check occurs.
See linkgit:git-config[1].
--no-show-forced-updates::
By default, git checks if a branch is force-updated during
fetch. Pass --no-show-forced-updates or set fetch.showForcedUpdates
to false to skip this check for performance reasons. If used during
'git-pull' the --ff-only option will still check for forced updates
before attempting a fast-forward update. See linkgit:git-config[1].
-4:: -4::
--ipv4:: --ipv4::
Use IPv4 addresses only, ignoring IPv6 addresses. Use IPv4 addresses only, ignoring IPv6 addresses.

View File

@ -3,6 +3,7 @@
#include "color.h" #include "color.h"
#include "help.h" #include "help.h"
int advice_fetch_show_forced_updates = 1;
int advice_push_update_rejected = 1; int advice_push_update_rejected = 1;
int advice_push_non_ff_current = 1; int advice_push_non_ff_current = 1;
int advice_push_non_ff_matching = 1; int advice_push_non_ff_matching = 1;
@ -60,6 +61,7 @@ static struct {
const char *name; const char *name;
int *preference; int *preference;
} advice_config[] = { } advice_config[] = {
{ "fetchShowForcedUpdates", &advice_fetch_show_forced_updates },
{ "pushUpdateRejected", &advice_push_update_rejected }, { "pushUpdateRejected", &advice_push_update_rejected },
{ "pushNonFFCurrent", &advice_push_non_ff_current }, { "pushNonFFCurrent", &advice_push_non_ff_current },
{ "pushNonFFMatching", &advice_push_non_ff_matching }, { "pushNonFFMatching", &advice_push_non_ff_matching },

View File

@ -3,6 +3,7 @@
#include "git-compat-util.h" #include "git-compat-util.h"
extern int advice_fetch_show_forced_updates;
extern int advice_push_update_rejected; extern int advice_push_update_rejected;
extern int advice_push_non_ff_current; extern int advice_push_non_ff_current;
extern int advice_push_non_ff_matching; extern int advice_push_non_ff_matching;

View File

@ -24,6 +24,8 @@
#include "list-objects-filter-options.h" #include "list-objects-filter-options.h"
#include "commit-reach.h" #include "commit-reach.h"
#define FORCED_UPDATES_DELAY_WARNING_IN_MS (10 * 1000)
static const char * const builtin_fetch_usage[] = { static const char * const builtin_fetch_usage[] = {
N_("git fetch [<options>] [<repository> [<refspec>...]]"), N_("git fetch [<options>] [<repository> [<refspec>...]]"),
N_("git fetch [<options>] <group>"), N_("git fetch [<options>] <group>"),
@ -39,6 +41,8 @@ enum {
}; };
static int fetch_prune_config = -1; /* unspecified */ 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 */ static int prune = -1; /* unspecified */
#define PRUNE_BY_DEFAULT 0 /* do we prune by default? */ #define PRUNE_BY_DEFAULT 0 /* do we prune by default? */
@ -80,6 +84,11 @@ static int git_fetch_config(const char *k, const char *v, void *cb)
return 0; return 0;
} }
if (!strcmp(k, "fetch.showforcedupdates")) {
fetch_show_forced_updates = git_config_bool(k, v);
return 0;
}
if (!strcmp(k, "submodule.recurse")) { if (!strcmp(k, "submodule.recurse")) {
int r = git_config_bool(k, v) ? int r = git_config_bool(k, v) ?
RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF; RECURSE_SUBMODULES_ON : RECURSE_SUBMODULES_OFF;
@ -172,6 +181,8 @@ static struct option builtin_fetch_options[] = {
OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options), OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
OPT_BOOL(0, "auto-gc", &enable_auto_gc, OPT_BOOL(0, "auto-gc", &enable_auto_gc,
N_("run 'gc --auto' after fetching")), N_("run 'gc --auto' after fetching")),
OPT_BOOL(0, "show-forced-updates", &fetch_show_forced_updates,
N_("check for forced-updates on all updated branches")),
OPT_END() OPT_END()
}; };
@ -710,6 +721,7 @@ static int update_local_ref(struct ref *ref,
enum object_type type; enum object_type type;
struct branch *current_branch = branch_get(NULL); struct branch *current_branch = branch_get(NULL);
const char *pretty_ref = prettify_refname(ref->name); const char *pretty_ref = prettify_refname(ref->name);
int fast_forward = 0;
type = oid_object_info(the_repository, &ref->new_oid, NULL); type = oid_object_info(the_repository, &ref->new_oid, NULL);
if (type < 0) if (type < 0)
@ -784,9 +796,18 @@ static int update_local_ref(struct ref *ref,
return r; return r;
} }
if (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; struct strbuf quickref = STRBUF_INIT;
int r; int r;
strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV); strbuf_add_unique_abbrev(&quickref, &current->object.oid, DEFAULT_ABBREV);
strbuf_addstr(&quickref, ".."); strbuf_addstr(&quickref, "..");
strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV); strbuf_add_unique_abbrev(&quickref, &ref->new_oid, DEFAULT_ABBREV);
@ -982,6 +1003,17 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
" 'git remote prune %s' to remove any old, conflicting " " 'git remote prune %s' to remove any old, conflicting "
"branches"), remote_name); "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: abort:
strbuf_release(&note); strbuf_release(&note);
free(url); free(url);

View File

@ -128,6 +128,7 @@ static char *opt_update_shallow;
static char *opt_refmap; static char *opt_refmap;
static char *opt_ipv4; static char *opt_ipv4;
static char *opt_ipv6; static char *opt_ipv6;
static int opt_show_forced_updates = -1;
static struct option pull_options[] = { static struct option pull_options[] = {
/* Shared options */ /* Shared options */
@ -240,6 +241,8 @@ static struct option pull_options[] = {
OPT_PASSTHRU('6', "ipv6", &opt_ipv6, NULL, OPT_PASSTHRU('6', "ipv6", &opt_ipv6, NULL,
N_("use IPv6 addresses only"), N_("use IPv6 addresses only"),
PARSE_OPT_NOARG), PARSE_OPT_NOARG),
OPT_BOOL(0, "show-forced-updates", &opt_show_forced_updates,
N_("check for forced-updates on all updated branches")),
OPT_END() OPT_END()
}; };
@ -549,6 +552,10 @@ static int run_fetch(const char *repo, const char **refspecs)
argv_array_push(&args, opt_ipv4); argv_array_push(&args, opt_ipv4);
if (opt_ipv6) if (opt_ipv6)
argv_array_push(&args, opt_ipv6); argv_array_push(&args, opt_ipv6);
if (opt_show_forced_updates > 0)
argv_array_push(&args, "--show-forced-updates");
else if (opt_show_forced_updates == 0)
argv_array_push(&args, "--no-show-forced-updates");
if (repo) { if (repo) {
argv_array_push(&args, repo); argv_array_push(&args, repo);

View File

@ -978,4 +978,27 @@ test_expect_success '--negotiation-tip limits "have" lines sent with HTTP protoc
check_negotiation_tip check_negotiation_tip
' '
test_expect_success '--no-show-forced-updates' '
mkdir forced-updates &&
(
cd forced-updates &&
git init &&
test_commit 1 &&
test_commit 2
) &&
git clone forced-updates forced-update-clone &&
git clone forced-updates no-forced-update-clone &&
git -C forced-updates reset --hard HEAD~1 &&
(
cd forced-update-clone &&
git fetch --show-forced-updates origin 2>output &&
test_i18ngrep "(forced update)" output
) &&
(
cd no-forced-update-clone &&
git fetch --no-show-forced-updates origin 2>output &&
! test_i18ngrep "(forced update)" output
)
'
test_done test_done