ref: 8c43c1ae1adf0409ddd8e268474600cb6341b2c3
parent: 5db1e72fff8404826e77d1e295f860505932c5ff
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Jul 27 13:37:47 EDT 2025
git: send more known refs, in hopes of smaller fetches we used to only say we had the branches we were pulling, but that meant that when pulling a new branch, we would say we had nothing, leading to a lot of duplicate data getting sent. This change the 20 most recent local branches as refs we know about, in the hopes that the remote can compute a smaller delta. The long term fix would be to write the request in parallel with reading the response, which would allow us to provide a great deal more information without blocking, but this will do the job for now.
--- a/sys/src/cmd/git/get.c
+++ b/sys/src/cmd/git/get.c
@@ -5,6 +5,8 @@
char *fetchbranch;
char *upstream = "origin";
+Hash heads[64];
+int nheads;
int listonly;
/*
@@ -302,7 +304,7 @@
continue;
for(j = 0; j < i; j++)
if(hasheq(&want[i], &want[j]))
- goto Next;
+ continue;
if((o = readobject(want[i])) != nil){
unref(o);
continue;
@@ -311,7 +313,6 @@
sysfatal("could not send want for %H", want[i]);
caps[0] = 0;
req = 1;
-Next: continue;
}
flushpkt(c);
@@ -337,6 +338,22 @@
nsent++;
}
/*
+ * The other branches we have probably make sense to send,
+ * since often we'll be pulling a new branch with objects
+ * that we already have; it's not entirely clear what we
+ * want to do here.
+ */
+ for(i = 0; i < nheads; i++){
+ if((o = readobject(heads[i])) == nil)
+ sysfatal("missing exected object: %H", have[i]);
+ if(fmtpkt(c, "have %H", o->hash) == -1)
+ sysfatal("write: %r");
+ enqueueparent(&haveq, o);
+ osadd(&hadobj, o);
+ unref(o);
+ nsent++;
+ }
+ /*
* While we could short circuit this and check if upstream has
* acked our objects, for the first 256 haves, this is simple
* enough.
@@ -467,7 +484,14 @@
case 'u': upstream=EARGF(usage()); break;
case 'd': chattygit++; break;
case 'l': listonly++; break;
- default: usage(); break;
+ case 'h':
+ if(nheads < nelem(heads))
+ if(hparse(&heads[nheads], EARGF(usage())) == 0)
+ nheads++;
+ break;
+ default:
+ usage();
+ break;
}ARGEND;
gitinit();
--- a/sys/src/cmd/git/pull
+++ b/sys/src/cmd/git/pull
@@ -9,7 +9,19 @@
dflag=()
if(! ~ $#debug 0)
dflag='-d'
- {git/get $dflag -u $upstream $url >[2=3] || die $status} | awk '
+ heads=`$nl{
+ # safe to split in awk, branch names may not
+ # have spaces or newlines.
+ git/query `$nl{
+ cd .git/refs && \
+ walk -f -emp heads remotes | \
+ sort -rn | \
+ awk '{print $2}'
+ }
+ }
+ if(! ~ $#heads 0)
+ heads='-h'^$heads
+ {git/get $dflag -u $upstream $heads $url >[2=3] || die $status} | awk '
/^remote refs\/(heads|tags)\//{
ref=$2
hash=$3
--
⑨