Junio C Hamano [off-list ref] writes:
"Stephen C. Tweedie" [off-list ref] writes:
quoted
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