]> git.ipfire.org Git - thirdparty/git.git/commitdiff
fetch: add --negotiation-restrict option
authorDerrick Stolee <stolee@gmail.com>
Tue, 19 May 2026 16:24:49 +0000 (16:24 +0000)
committerJunio C Hamano <gitster@pobox.com>
Wed, 20 May 2026 02:33:23 +0000 (11:33 +0900)
The --negotiation-tip option to 'git fetch' and 'git pull' allows users
to specify that they want to focus negotiation on a small set of
references. This is a _restriction_ on the negotiation set, helping to
focus the negotiation when the ref count is high. However, it doesn't
allow for the ability to opportunistically select references beyond that
list.

This subtle detail that this is a 'maximum set' and not a 'minimum set'
is not immediately clear from the option name. This makes it more
complicated to add a new option that provides the complementary behavior
of a minimum set.

For now, create a new synonym option, --negotiation-restrict, that
behaves identically to --negotiation-tip. Update the documentation to
make it clear that this new name is the preferred option, but we keep
the old name for compatibility. Mark --negotiation-tip as an alias of the
new, preferred option.

Update a few warning messages with the new option, but also make them
translatable with the option name inserted by formatting. At least one
of these messages will be reused later for a new option.

Reviewed-by: Matthew John Cheetham <mjcheetham@outlook.com>
Signed-off-by: Derrick Stolee <stolee@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config/fetch.adoc
Documentation/fetch-options.adoc
builtin/fetch.c
builtin/pull.c
send-pack.c
t/t5510-fetch.sh
t/t5702-protocol-v2.sh
transport-helper.c

index cd40db0cad1c3699c5489d1ab25306a5d7a5e346..04ac90912d3a58a6696ed23f391819f3a2445f11 100644 (file)
@@ -76,7 +76,7 @@
        default is `skipping`.  Unknown values will cause `git fetch` to
        error out.
 +
-See also the `--negotiate-only` and `--negotiation-tip` options to
+See also the `--negotiate-only` and `--negotiation-restrict` options to
 linkgit:git-fetch[1].
 
 `fetch.showForcedUpdates`::
index 81a9d7f9bbc11db582f84b6022df01832528b24c..d39cecb44689911172095bfa8c8f80ef0b84720e 100644 (file)
@@ -49,6 +49,7 @@ the current repository has the same history as the source repository.
        `.git/shallow`. This option updates `.git/shallow` and accepts such
        refs.
 
+`--negotiation-restrict=(<commit>|<glob>)`::
 `--negotiation-tip=(<commit>|<glob>)`::
        By default, Git will report, to the server, commits reachable
        from all local refs to find common commits in an attempt to
@@ -58,6 +59,9 @@ the current repository has the same history as the source repository.
        local ref is likely to have commits in common with the
        upstream ref being fetched.
 +
+`--negotiation-restrict` is the preferred name for this option;
+`--negotiation-tip` is accepted as a synonym.
++
 This option may be specified more than once; if so, Git will report
 commits reachable from any of the given commits.
 +
@@ -71,7 +75,7 @@ configuration variables documented in linkgit:git-config[1], and the
 
 `--negotiate-only`::
        Do not fetch anything from the server, and instead print the
-       ancestors of the provided `--negotiation-tip=` arguments,
+       ancestors of the provided `--negotiation-restrict=` arguments,
        which we have in common with the server.
 +
 This is incompatible with `--recurse-submodules=(yes|on-demand)`.
index 4795b2a13c30e3c1db8450db9c39fec3ffe69f2c..fc950fe35b5e734ebf854015609366f53ad35c01 100644 (file)
@@ -1558,8 +1558,8 @@ static void add_negotiation_tips(struct git_transport_options *smart_options)
                refs_for_each_ref_ext(get_main_ref_store(the_repository),
                                      add_oid, oids, &opts);
                if (old_nr == oids->nr)
-                       warning("ignoring --negotiation-tip=%s because it does not match any refs",
-                               s);
+                       warning(_("ignoring %s=%s because it does not match any refs"),
+                               "--negotiation-restrict", s);
        }
        smart_options->negotiation_tips = oids;
 }
@@ -1599,7 +1599,8 @@ static struct transport *prepare_transport(struct remote *remote, int deepen,
                if (transport->smart_options)
                        add_negotiation_tips(transport->smart_options);
                else
-                       warning("ignoring --negotiation-tip because the protocol does not support it");
+                       warning(_("ignoring %s because the protocol does not support it"),
+                               "--negotiation-restrict");
        }
        return transport;
 }
@@ -2565,8 +2566,9 @@ int cmd_fetch(int argc,
                               N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg),
                OPT_STRING_LIST('o', "server-option", &server_options, N_("server-specific"), N_("option to transmit")),
                OPT_IPVERSION(&family),
-               OPT_STRING_LIST(0, "negotiation-tip", &negotiation_tip, N_("revision"),
+               OPT_STRING_LIST(0, "negotiation-restrict", &negotiation_tip, N_("revision"),
                                N_("report that we have only objects reachable from this object")),
+               OPT_ALIAS(0, "negotiation-tip", "negotiation-restrict"),
                OPT_BOOL(0, "negotiate-only", &negotiate_only,
                         N_("do not fetch a packfile; instead, print ancestors of negotiation tips")),
                OPT_PARSE_LIST_OBJECTS_FILTER(&filter_options),
@@ -2657,7 +2659,8 @@ int cmd_fetch(int argc,
        }
 
        if (negotiate_only && !negotiation_tip.nr)
-               die(_("--negotiate-only needs one or more --negotiation-tip=*"));
+               die(_("%s needs one or more %s"), "--negotiate-only",
+                   "--negotiation-restrict=*");
 
        if (deepen_relative) {
                if (deepen_relative < 0)
index 7e67fdce97fd1d8543d6412e36c6c3ce41df9430..cc6ce485fc4e700c4ec65aaffed3eb99c7dbd859 100644 (file)
@@ -996,9 +996,10 @@ int cmd_pull(int argc,
                OPT_PASSTHRU('6',  "ipv6", &opt_ipv6, NULL,
                        N_("use IPv6 addresses only"),
                        PARSE_OPT_NOARG),
-               OPT_PASSTHRU_ARGV(0, "negotiation-tip", &opt_fetch, N_("revision"),
+               OPT_PASSTHRU_ARGV(0, "negotiation-restrict", &opt_fetch, N_("revision"),
                        N_("report that we have only objects reachable from this object"),
                        0),
+               OPT_ALIAS(0, "negotiation-tip", "negotiation-restrict"),
                OPT_BOOL(0, "show-forced-updates", &opt_show_forced_updates,
                         N_("check for forced-updates on all updated branches")),
                OPT_PASSTHRU(0, "set-upstream", &set_upstream, NULL,
index 67d6987b1ccd7ed8a758c407e1e01bf7e53d6bd0..3d5d36ba3baa2e80bf09f43a2af6131ea1c83feb 100644 (file)
@@ -447,7 +447,7 @@ static void get_commons_through_negotiation(struct repository *r,
        strvec_pushl(&child.args, "fetch", "--negotiate-only", NULL);
        for (ref = remote_refs; ref; ref = ref->next) {
                if (!is_null_oid(&ref->new_oid)) {
-                       strvec_pushf(&child.args, "--negotiation-tip=%s",
+                       strvec_pushf(&child.args, "--negotiation-restrict=%s",
                                     oid_to_hex(&ref->new_oid));
                        nr_negotiation_tip++;
                }
index 5dcb4b51a47d8868b65cffd76e59f948bd49f21b..dc3ce56d84c743bf7e65e718e95e25fc1c5b35b8 100755 (executable)
@@ -1460,6 +1460,31 @@ EOF
        test_cmp fatal-expect fatal-actual
 '
 
+test_expect_success '--negotiation-restrict limits "have" lines sent' '
+       setup_negotiation_tip server server 0 &&
+       GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
+               --negotiation-restrict=alpha_1 --negotiation-restrict=beta_1 \
+               origin alpha_s beta_s &&
+       check_negotiation_tip
+'
+
+test_expect_success '--negotiation-restrict understands globs' '
+       setup_negotiation_tip server server 0 &&
+       GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
+               --negotiation-restrict=*_1 \
+               origin alpha_s beta_s &&
+       check_negotiation_tip
+'
+
+test_expect_success '--negotiation-restrict and --negotiation-tip can be mixed' '
+       setup_negotiation_tip server server 0 &&
+       GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
+               --negotiation-restrict=alpha_1 \
+               --negotiation-tip=beta_1 \
+               origin alpha_s beta_s &&
+       check_negotiation_tip
+'
+
 test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
        git init df-conflict &&
        (
index f826ac46a5be5a129f1f3824f7759bfbd3495e7e..9f6cf4142d5b83bd5b3ab9a3a08d3084fd8774d3 100755 (executable)
@@ -869,14 +869,14 @@ setup_negotiate_only () {
        test_commit -C client three
 }
 
-test_expect_success 'usage: --negotiate-only without --negotiation-tip' '
+test_expect_success 'usage: --negotiate-only without --negotiation-restrict' '
        SERVER="server" &&
        URI="file://$(pwd)/server" &&
 
        setup_negotiate_only "$SERVER" "$URI" &&
 
        cat >err.expect <<-\EOF &&
-       fatal: --negotiate-only needs one or more --negotiation-tip=*
+       fatal: --negotiate-only needs one or more --negotiation-restrict=*
        EOF
 
        test_must_fail git -c protocol.version=2 -C client fetch \
index 4d95d84f9e4d05db5117016bcdacadf3a4fe46b2..dd78d406681f0e69c7e459ce5bb3550d3d10e6ba 100644 (file)
@@ -755,7 +755,8 @@ static int fetch_refs(struct transport *transport,
        }
 
        if (data->transport_options.negotiation_tips)
-               warning("Ignoring --negotiation-tip because the protocol does not support it.");
+               warning(_("ignoring %s because the protocol does not support it."),
+                       "--negotiation-restrict");
 
        if (data->fetch)
                return fetch_with_fetch(transport, nr_heads, to_fetch);