Linus Torvalds [off-list ref] writes:
The way to fix both these problems at once would be to add a flag to the
"for_each_ref()", which says whether it followed a link, or whether it was
already packed, so that we wouldn't pack symlinks at all, and we wouldn't
add already-packed refs to the "keeprefs" list.
But that requires a sligh semantic extension to "do_for_each_ref()" (and
"struct ref_list" needs a flag to say whether it was looked up through a
symlink).
I was thinking that the easy way to solve it is to just _pack_ everything
(the way we do now - incorrectly for symrefs), but never prune a symref.
I see. Thanks for pointing out the issue with symrefs. I think
clone with --use-separate-remote creates remote/$that_repo/HEAD
that points at the branch the remote side's HEAD points at (to
be precise, the one it guessed the remote side's HEAD points
at), so this is a real issue already.
I wanted to update for_each_ref() anyway for other reasons (it
really should take callback data -- the way the current users
use global variables to work this around is eyesore), so
hopefully I'll find time to take a look at it.
Rough outline:
- for_each_ref() and friends become:
typedef int each_ref_fn(const char *refname,
const unsigned char *sha1,
#define REF_IS_SYMREF 01
#define REF_IS_PACKED 02
int flags, /* above bits or'ed */
void *cb_data);
int for_each_ref(each_ref_fn fn, void *cb_data);
- handle_one_ref notices a symref and ignores it; it remembers
refs that are not symref and are still loose for later
pruning under --prune.
We might want to update the initial handshake of upload-pack
protocol so that peek-remote and fetch-pack can tell which one
is a symref pointing at what. Do the usual server_capabilities
discovery in connect.c::get_remote_heads(), and if an extension
"symref" is supported than ask for symref information (typically
we would only get "HEAD points at refs/heads/foo" and nothing
else). Then git-clone.sh does not have to make a guess. But
that is a separate topic.