From: Junio C Hamano Date: Thu, 5 Apr 2007 10:22:55 +0000 (-0700) Subject: git-fetch: use fetch--tool pick-rref to avoid local fetch from alternate X-Git-Tag: v1.5.2-rc0~22^2~1 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=e3c6f240fd9c5bdeb33f2d47adc859f37935e2df;p=git.git git-fetch: use fetch--tool pick-rref to avoid local fetch from alternate When we are fetching from a repository that is on a local filesystem, first check if we have all the objects that we are going to fetch available locally, by not just checking the tips of what we are fetching, but with a full reachability analysis to our existing refs. In such a case, we do not have to run git-fetch-pack which would send many needless objects. This is especially true when the other repository is an alternate of the current repository (e.g. perhaps the repository was created by running "git clone -l -s" from there). The useless objects transferred used to be discarded when they were expanded by git-unpack-objects called from git-fetch-pack, but recent git-fetch-pack prefers to keep the data it receives from the other end without exploding them into loose objects, resulting in a pack full of duplicated data when fetching from your own alternate. This also uses fetch--tool pick-rref on dumb transport side to remove a shell loop to do the same. Signed-off-by: Junio C Hamano --- diff --git a/git-fetch.sh b/git-fetch.sh index b04bd553f..832b20cce 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -177,9 +177,33 @@ fetch_all_at_once () { git-bundle unbundle "$remote" $rref || echo failed "$remote" else - git-fetch-pack --thin $exec $keep $shallow_depth \ - $quiet $no_progress "$remote" $rref || - echo failed "$remote" + if test -d "$remote" && + + # The remote might be our alternate. With + # this optimization we will bypass fetch-pack + # altogether, which means we cannot be doing + # the shallow stuff at all. + test ! -f "$GIT_DIR/shallow" && + test -z "$shallow_depth" && + + # See if all of what we are going to fetch are + # connected to our repository's tips, in which + # case we do not have to do any fetch. + theirs=$(git-fetch--tool -s pick-rref \ + "$rref" "$ls_remote_result") && + + # This will barf when $theirs reach an object that + # we do not have in our repository. Otherwise, + # we already have everything the fetch would bring in. + git-rev-list --objects $theirs --not --all \ + >/dev/null 2>/dev/null + then + git-fetch--tool pick-rref "$rref" "$ls_remote_result" + else + git-fetch-pack --thin $exec $keep $shallow_depth \ + $quiet $no_progress "$remote" $rref || + echo failed "$remote" + fi fi ) | ( @@ -239,16 +263,8 @@ fetch_per_ref () { fi # Find $remote_name from ls-remote output. - head=$( - IFS=' ' - echo "$ls_remote_result" | - while read sha1 name - do - test "z$name" = "z$remote_name" || continue - echo "$sha1" - break - done - ) + head=$(git-fetch--tool -s pick-rref \ + "$remote_name" "$ls_remote_result") expr "z$head" : "z$_x40\$" >/dev/null || die "No such ref $remote_name at $remote" echo >&2 "Fetching $remote_name from $remote using $proto"