Junio C Hamano <junkio@xxxxxxx> writes: > "Stephen C. Tweedie" <sct@xxxxxxxxxx> writes: > >> send_pack() >> then skips all other refs by doing a >> >> if (!ref->peer_ref) >> continue; >> >> Unfortunately, exec_rev_list() is missing this, and it tries to ask >> git-rev-list for the commit objects of *every* ref on the remote_refs >> list, even if they have been explicitly excluded by match_refs() and >> have no peer_ref. So with this huge repository, I can't even push a >> single refspec without bumping into the limit of 900 refs. > > IIRC, the distinction was deliberate. send_pack() excludes > what did not match because it does not want to send them. > rev_list() adds what we know they have to "do not bother to > send" list to make the resulting pack smaller. The time where > it matters most is when you are pushing a new branch head (or a > tag). > > I think the exec_rev_list logic should be taught to first > include all the positive refs (i.e. the ones we are going to > send), and then as many the negative refs (i.e. the ones we know > they have), from newer to older, as they fit without triggering > "argument list too long". That is, something like this. -- >8 -- Do not give up running rev-list when remote has insanely large number of refs. --- cd /opt/packrat/playpen/public/in-place/git/git.junio/ git diff diff --git a/send-pack.c b/send-pack.c index 990be3f..cfd0eeb 100644 --- a/send-pack.c +++ b/send-pack.c @@ -37,24 +37,27 @@ static void exec_pack_objects(void) static void exec_rev_list(struct ref *refs) { + struct ref *ref; static char *args[1000]; int i = 0; args[i++] = "rev-list"; /* 0 */ args[i++] = "--objects"; /* 1 */ - while (refs) { - char *buf = malloc(100); + for (ref = refs; refs; refs = refs->next) { + char *buf = malloc(41); if (i > 900) die("git-rev-list environment overflow"); - if (!is_zero_sha1(refs->old_sha1) && - has_sha1_file(refs->old_sha1)) { + if (!is_zero_sha1(refs->new_sha1)) { args[i++] = buf; - snprintf(buf, 50, "^%s", sha1_to_hex(refs->old_sha1)); - buf += 50; + snprintf(buf, 41, "%s", sha1_to_hex(refs->new_sha1)); } - if (!is_zero_sha1(refs->new_sha1)) { + } + for (ref = refs; i < 900 && refs; refs = refs->next) { + char *buf = malloc(42); + if (!is_zero_sha1(refs->old_sha1) && + has_sha1_file(refs->old_sha1)) { args[i++] = buf; - snprintf(buf, 50, "%s", sha1_to_hex(refs->new_sha1)); + snprintf(buf, 42, "^%s", sha1_to_hex(refs->old_sha1)); } refs = refs->next; } Compilation finished at Tue Feb 21 18:52:49 - : send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html