]> git.ipfire.org Git - thirdparty/git.git/commitdiff
push: don't fetch commit object when checking existence
authorTom Hughes <tom@compton.nu>
Wed, 22 May 2024 20:15:40 +0000 (21:15 +0100)
committerJunio C Hamano <gitster@pobox.com>
Wed, 22 May 2024 20:46:08 +0000 (13:46 -0700)
If we're checking to see whether to tell the user to do a fetch
before pushing there's no need for us to actually fetch the object
from the remote if the clone is partial.

Because the promisor doesn't do negotiation actually trying to do
the fetch of the new head can be very expensive as it will try and
include history that we already have and it just results in rejecting
the push with a different message, and in behavior that is different
to a clone that is not partial.

Signed-off-by: Tom Hughes <tom@compton.nu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
remote.c
t/t0410-partial-clone.sh

index 2b650b813b741f722a5f6c69f359a1f53249bcb1..20395bbbd04bec7d79af8f23a09da56fafa72845 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -1773,7 +1773,7 @@ void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
                if (!reject_reason && !ref->deletion && !is_null_oid(&ref->old_oid)) {
                        if (starts_with(ref->name, "refs/tags/"))
                                reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
-                       else if (!repo_has_object_file(the_repository, &ref->old_oid))
+                       else if (!repo_has_object_file_with_flags(the_repository, &ref->old_oid, OBJECT_INFO_SKIP_FETCH_OBJECT))
                                reject_reason = REF_STATUS_REJECT_FETCH_FIRST;
                        else if (!lookup_commit_reference_gently(the_repository, &ref->old_oid, 1) ||
                                 !lookup_commit_reference_gently(the_repository, &ref->new_oid, 1))
index 88a66f09040ce0aa2a3a653579d6c3685e750ba1..7797391c03f04a20b18818cee530072355ccaba1 100755 (executable)
@@ -689,6 +689,25 @@ test_expect_success 'lazy-fetch when accessing object not in the_repository' '
        ! grep "[?]$FILE_HASH" out
 '
 
+test_expect_success 'push should not fetch new commit objects' '
+       rm -rf server client &&
+       test_create_repo server &&
+       test_config -C server uploadpack.allowfilter 1 &&
+       test_config -C server uploadpack.allowanysha1inwant 1 &&
+       test_commit -C server server1 &&
+
+       git clone --filter=blob:none "file://$(pwd)/server" client &&
+       test_commit -C client client1 &&
+
+       test_commit -C server server2 &&
+       COMMIT=$(git -C server rev-parse server2) &&
+
+       test_must_fail git -C client push 2>err &&
+       grep "fetch first" err &&
+       git -C client rev-list --objects --missing=print "$COMMIT" >objects &&
+       grep "^[?]$COMMIT" objects
+'
+
 . "$TEST_DIRECTORY"/lib-httpd.sh
 start_httpd