'git fetch' uses git transport to compress and transfer all the commits even though they're on a local machine -- both very slow and space consuming.
Setting 'alternates' before fetching solves the issue partially since the commits no longer need to be transferred. The checkout is still slow since git needs to recheck all of them. Instead, just set 'alternates' and copy the refs manually. This is pretty much what 'git clone --shared' does. And we can't use 'git clone' because it refuses non-empty destinations. This also makes it possible to use the same checkout method for shallow clones with <git-1.9 (git-1.9 finally allows clones and fetches using shallow repos). --- eclass/git-r3.eclass | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/eclass/git-r3.eclass b/eclass/git-r3.eclass index c00b3a0..892ed07 100644 --- a/eclass/git-r3.eclass +++ b/eclass/git-r3.eclass @@ -458,13 +458,14 @@ git-r3_checkout() { # non-empty directories. git init --quiet || die - set -- git fetch --update-head-ok "${orig_repo}" \ - "refs/heads/*:refs/heads/*" \ - "refs/tags/*:refs/tags/*" \ - "refs/notes/*:refs/notes/*" - - echo "${@}" >&2 - "${@}" || die "git fetch into checkout dir failed" + # setup 'alternates' to avoid copying objects + echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die + # now copy the refs + # [htn]* safely catches heads, tags, notes without complaining + # on non-existing ones, and omits internal 'git-r3' ref + cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die + + # (no need to copy HEAD, we will set it via checkout) set -- git checkout --quiet if [[ ${remote_ref} ]]; then -- 1.8.3.2